summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Kneiser <matt.kneiser@mongodb.com>2022-09-29 04:14:06 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-09-29 05:17:36 +0000
commit1990f6a8a6cab84e2ddd05ab0469b9481b962ed5 (patch)
tree49361f6c55c71d6b01b9cec319d773dd21be2755
parent1912e879e904b96a331cd2a2d20e7abf23684359 (diff)
downloadmongo-1990f6a8a6cab84e2ddd05ab0469b9481b962ed5.tar.gz
SERVER-69387 Debug Selectively Restored Sharded Collections
-rw-r--r--jstests/sharding/run_restore.js14
-rw-r--r--jstests/sharding/run_restore_unsharded.js4
-rw-r--r--src/mongo/db/s/config/configsvr_run_restore_command.cpp64
3 files changed, 68 insertions, 14 deletions
diff --git a/jstests/sharding/run_restore.js b/jstests/sharding/run_restore.js
index 1d0a5dc821f..d16560f8725 100644
--- a/jstests/sharding/run_restore.js
+++ b/jstests/sharding/run_restore.js
@@ -116,8 +116,20 @@ assert.commandWorked(conn.getDB("admin").runCommand({setParameter: 1, logLevel:
assert.commandFailedWithCode(conn.getDB("admin").runCommand({_configsvrRunRestore: 1}),
ErrorCodes.NamespaceNotFound);
-// Create the "local.system.collections_to_restore" collection and insert "test.a".
+let [_, uuidStr] = aCollUUID.toString().match(/"((?:\\.|[^"\\])*)"/);
+assert.commandWorked(conn.getDB("local").getCollection("system.collections_to_restore").insert({
+ ns: "test.a",
+ uuid: uuidStr
+}));
+
+// The "local.system.collections_to_restore" collection must have UUID as the correct type.
+assert.commandFailedWithCode(conn.getDB("admin").runCommand({_configsvrRunRestore: 1}),
+ ErrorCodes.BadValue);
+
+// Recreate the "local.system.collections_to_restore" collection and insert 'test.a'.
+assert(conn.getDB("local").getCollection("system.collections_to_restore").drop());
assert.commandWorked(conn.getDB("local").createCollection("system.collections_to_restore"));
+
assert.commandWorked(conn.getDB("local").getCollection("system.collections_to_restore").insert({
ns: "test.a",
uuid: aCollUUID
diff --git a/jstests/sharding/run_restore_unsharded.js b/jstests/sharding/run_restore_unsharded.js
index e55377bfaa9..d9ad5d0edc9 100644
--- a/jstests/sharding/run_restore_unsharded.js
+++ b/jstests/sharding/run_restore_unsharded.js
@@ -11,8 +11,8 @@
load("jstests/libs/feature_flag_util.js");
-const s =
- new ShardingTest({name: "runRestore", shards: 2, mongos: 1, config: 1, other: {chunkSize: 1}});
+const s = new ShardingTest(
+ {name: "runRestoreUnsharded", shards: 2, mongos: 1, config: 1, other: {chunkSize: 1}});
let mongos = s.s0;
let db = s.getDB("test");
diff --git a/src/mongo/db/s/config/configsvr_run_restore_command.cpp b/src/mongo/db/s/config/configsvr_run_restore_command.cpp
index 4790aefa1f8..ef9de4c5231 100644
--- a/src/mongo/db/s/config/configsvr_run_restore_command.cpp
+++ b/src/mongo/db/s/config/configsvr_run_restore_command.cpp
@@ -37,6 +37,8 @@
#include "mongo/db/repl/storage_interface_impl.h"
#include "mongo/logv2/log.h"
#include "mongo/stdx/unordered_map.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/uuid.h"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding
@@ -71,8 +73,27 @@ ShouldRestoreDocument shouldRestoreDocument(OperationContext* opCtx,
findRequest.setLimit(1);
DBDirectClient client(opCtx);
- return client.find(findRequest)->itcount() > 0 ? ShouldRestoreDocument::kYes
- : ShouldRestoreDocument::kNo;
+ auto resultCount = client.find(findRequest)->itcount();
+
+ // Log in cases where the schema is not adhered to.
+ if (resultCount == 0 && uuid) {
+ auto schemaCheckFindRequest =
+ FindCommandRequest(NamespaceString::kConfigsvrRestoreNamespace);
+ auto collectionsToRestore = client.find(schemaCheckFindRequest);
+ while (collectionsToRestore->more()) {
+ auto doc = collectionsToRestore->next();
+ try {
+ (void)UUID::parse(doc);
+ } catch (const AssertionException&) {
+ uasserted(ErrorCodes::BadValue,
+ str::stream() << "The uuid field of '" << doc.toString() << "' in '"
+ << NamespaceString::kConfigsvrRestoreNamespace.toString()
+ << "' needs to be of type UUID");
+ }
+ }
+ }
+
+ return resultCount > 0 ? ShouldRestoreDocument::kYes : ShouldRestoreDocument::kNo;
}
std::set<std::string> getDatabasesToRestore(OperationContext* opCtx) {
@@ -164,12 +185,11 @@ public:
restoreColl);
}
- // Keeps track of database names for collections restored. Databases with no collections
- // restored will have their entries removed in the config collections.
- std::set<std::string> databasesRestored = getDatabasesToRestore(opCtx);
-
for (const auto& collectionEntry : kCollectionEntries) {
const NamespaceString& nss = collectionEntry.first;
+ boost::optional<std::string> nssFieldName = collectionEntry.second.first;
+ boost::optional<std::string> uuidFieldName = collectionEntry.second.second;
+
LOGV2(6261300, "1st Phase - Restoring collection entries", logAttrs(nss));
CollectionPtr coll =
@@ -186,9 +206,6 @@ public:
while (cursor->more()) {
auto doc = cursor->next();
- boost::optional<std::string> nssFieldName = collectionEntry.second.first;
- boost::optional<std::string> uuidFieldName = collectionEntry.second.second;
-
boost::optional<NamespaceString> docNss = boost::none;
boost::optional<UUID> docUUID = boost::none;
@@ -210,6 +227,11 @@ public:
uassertStatusOK(swDocUUID);
docUUID = swDocUUID.getValue();
+ LOGV2_DEBUG(6938701,
+ 1,
+ "uuid found",
+ "uuid"_attr = uuidFieldName,
+ "docUUID"_attr = docUUID);
}
ShouldRestoreDocument shouldRestore = shouldRestoreDocument(opCtx, docNss, docUUID);
@@ -218,7 +240,9 @@ public:
1,
"Found document",
"doc"_attr = doc,
- "shouldRestore"_attr = shouldRestore);
+ "shouldRestore"_attr = shouldRestore,
+ "db"_attr = coll->ns().db().toString(),
+ "docNss"_attr = docNss);
if (shouldRestore == ShouldRestoreDocument::kYes ||
shouldRestore == ShouldRestoreDocument::kMaybe) {
@@ -226,12 +250,22 @@ public:
}
// The collection for this document was not restored, delete it.
+ LOGV2_DEBUG(6938702,
+ 1,
+ "Deleting collection that was not restored",
+ "db"_attr = coll->ns().db().toString(),
+ "uuid"_attr = coll->uuid(),
+ "_id"_attr = doc.getField("_id"));
NamespaceStringOrUUID nssOrUUID(coll->ns().db().toString(), coll->uuid());
uassertStatusOK(repl::StorageInterface::get(opCtx)->deleteById(
opCtx, nssOrUUID, doc.getField("_id")));
}
}
+ // Keeps track of database names for collections restored. Databases with no collections
+ // restored will have their entries removed in the config collections.
+ std::set<std::string> databasesRestored = getDatabasesToRestore(opCtx);
+
{
const std::vector<NamespaceString> databasesEntries = {
NamespaceString("config.databases")};
@@ -267,7 +301,9 @@ public:
1,
"Found document",
"doc"_attr = doc,
- "shouldRestore"_attr = shouldRestore);
+ "shouldRestore"_attr = shouldRestore,
+ "db"_attr = coll->ns().db().toString(),
+ "dbNss"_attr = dbNss.toString());
if (shouldRestore) {
// This database had at least one collection restored.
@@ -275,6 +311,12 @@ public:
}
// No collection for this database was restored, delete it.
+ LOGV2_DEBUG(6938703,
+ 1,
+ "Deleting database that was not restored",
+ "db"_attr = coll->ns().db().toString(),
+ "uuid"_attr = coll->uuid(),
+ "_id"_attr = doc.getField("_id"));
NamespaceStringOrUUID nssOrUUID(coll->ns().db().toString(), coll->uuid());
uassertStatusOK(repl::StorageInterface::get(opCtx)->deleteById(
opCtx, nssOrUUID, doc.getField("_id")));