summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-08-22 09:57:26 -0400
committerGregory Wlodarek <gregory.wlodarek@mongodb.com>2019-08-22 13:22:38 -0400
commit4db2f7c5f0fa6a19be5cb5f36ad29b670f162813 (patch)
treed1e9031af921fd8d441d9edbf394301b5f7d22c0 /src
parente12f75c9e74aa37c66797cd0c4e8f9407f1cb2d7 (diff)
downloadmongo-4db2f7c5f0fa6a19be5cb5f36ad29b670f162813.tar.gz
SERVER-41811 Deduplicate CollectionValidation::_genericRecordStoreValidate and ValidateAdaptor::traverseRecordStore
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/collection_validation.cpp110
-rw-r--r--src/mongo/db/catalog/validate_adaptor.cpp9
-rw-r--r--src/mongo/db/catalog/validate_adaptor.h1
3 files changed, 15 insertions, 105 deletions
diff --git a/src/mongo/db/catalog/collection_validation.cpp b/src/mongo/db/catalog/collection_validation.cpp
index 082f7964169..a9e85c9b289 100644
--- a/src/mongo/db/catalog/collection_validation.cpp
+++ b/src/mongo/db/catalog/collection_validation.cpp
@@ -53,97 +53,6 @@ namespace {
using ValidateResultsMap = std::map<string, ValidateResults>;
/**
- * General validation logic for any RecordStore. Performs sanity checks to confirm that each
- * record in the store is valid according to the given ValidateAdaptor and updates
- * record store stats to match.
- */
-void _genericRecordStoreValidate(
- OperationContext* opCtx,
- RecordStore* recordStore,
- ValidateAdaptor* indexValidator,
- const RecordId& firstRecordId,
- const std::unique_ptr<SeekableRecordCursor>& traverseRecordStoreCursor,
- const std::unique_ptr<SeekableRecordCursor>& seekRecordStoreCursor,
- ValidateResults* results,
- BSONObjBuilder* output) {
- long long nrecords = 0;
- long long dataSizeTotal = 0;
- long long nInvalid = 0;
-
- results->valid = true;
- int interruptInterval = 4096;
- RecordId prevRecordId;
-
- for (auto record = traverseRecordStoreCursor->seekExact(firstRecordId); record;
- record = traverseRecordStoreCursor->next()) {
- if (!(nrecords % interruptInterval)) {
- opCtx->checkForInterrupt();
- }
- ++nrecords;
- auto dataSize = record->data.size();
- dataSizeTotal += dataSize;
- size_t validatedSize;
- Status status = indexValidator->validateRecord(
- record->id, record->data, seekRecordStoreCursor, &validatedSize);
-
- // Check to ensure isInRecordIdOrder() is being used properly.
- if (prevRecordId.isValid()) {
- invariant(prevRecordId < record->id);
- }
-
- // ValidatedSize = dataSize is not a general requirement as some storage engines may use
- // padding, but we still require that they return the unpadded record data.
- if (!status.isOK() || validatedSize != static_cast<size_t>(dataSize)) {
- if (results->valid) {
- // Only log once.
- results->errors.push_back("detected one or more invalid documents (see logs)");
- }
- nInvalid++;
- results->valid = false;
- log() << "document at location: " << record->id << " is corrupted";
- }
-
- prevRecordId = record->id;
- }
-
- if (results->valid) {
- recordStore->updateStatsAfterRepair(opCtx, nrecords, dataSizeTotal);
- }
-
- output->append("nInvalidDocuments", nInvalid);
- output->appendNumber("nrecords", nrecords);
-}
-
-void _validateRecordStore(OperationContext* opCtx,
- RecordStore* recordStore,
- ValidateCmdLevel level,
- bool background,
- ValidateAdaptor* indexValidator,
- const RecordId& firstRecordId,
- const std::unique_ptr<SeekableRecordCursor>& traverseRecordStoreCursor,
- const std::unique_ptr<SeekableRecordCursor>& seekRecordStoreCursor,
- ValidateResults* results,
- BSONObjBuilder* output) {
- if (background) {
- indexValidator->traverseRecordStore(recordStore,
- firstRecordId,
- traverseRecordStoreCursor,
- seekRecordStoreCursor,
- results,
- output);
- } else {
- _genericRecordStoreValidate(opCtx,
- recordStore,
- indexValidator,
- firstRecordId,
- traverseRecordStoreCursor,
- seekRecordStoreCursor,
- results,
- output);
- }
-}
-
-/**
* Opens a cursor on each index in the given 'indexCatalog'.
*
* Returns a map from indexName -> indexCursor.
@@ -502,19 +411,16 @@ Status validate(OperationContext* opCtx,
// Validate the record store.
log(LogComponent::kIndex) << "validating collection " << coll->ns() << uuidString;
- // In _validateRecordStore(), the index validator keeps track the records in the record
+ // In traverseRecordStore(), the index validator keeps track the records in the record
// store so that _validateIndexes() can confirm that the index entries match the records in
// the collection.
- _validateRecordStore(opCtx,
- coll->getRecordStore(),
- level,
- background,
- &indexValidator,
- firstRecordId,
- traverseRecordStoreCursor,
- seekRecordStoreCursor,
- results,
- output);
+ indexValidator.traverseRecordStore(coll->getRecordStore(),
+ firstRecordId,
+ traverseRecordStoreCursor,
+ seekRecordStoreCursor,
+ background,
+ results,
+ output);
// Validate in-memory catalog information with persisted info.
_validateCatalogEntry(opCtx, coll, coll->getValidatorDoc(), results);
diff --git a/src/mongo/db/catalog/validate_adaptor.cpp b/src/mongo/db/catalog/validate_adaptor.cpp
index 700aa87c360..f8dc22a48a4 100644
--- a/src/mongo/db/catalog/validate_adaptor.cpp
+++ b/src/mongo/db/catalog/validate_adaptor.cpp
@@ -219,6 +219,7 @@ void ValidateAdaptor::traverseRecordStore(
const RecordId& firstRecordId,
const std::unique_ptr<SeekableRecordCursor>& traverseRecordStoreCursor,
const std::unique_ptr<SeekableRecordCursor>& seekRecordStoreCursor,
+ bool background,
ValidateResults* results,
BSONObjBuilder* output) {
long long nrecords = 0;
@@ -247,8 +248,8 @@ void ValidateAdaptor::traverseRecordStore(
invariant(prevRecordId < record->id);
}
- // While some storage engines may use padding, we still require that they return the
- // unpadded record data.
+ // validatedSize = dataSize is not a general requirement as some storage engines may use
+ // padding, but we still require that they return the unpadded record data.
if (!status.isOK() || validatedSize != static_cast<size_t>(dataSize)) {
if (results->valid) {
// Only log once.
@@ -262,7 +263,9 @@ void ValidateAdaptor::traverseRecordStore(
prevRecordId = record->id;
}
- if (results->valid) {
+ // Do not update the record store stats if we're in the background as we've validated a
+ // checkpoint and it may not have the most up-to-date changes.
+ if (results->valid && !background) {
recordStore->updateStatsAfterRepair(_opCtx, nrecords, dataSizeTotal);
}
diff --git a/src/mongo/db/catalog/validate_adaptor.h b/src/mongo/db/catalog/validate_adaptor.h
index aefa26dc41b..316c8ae42b1 100644
--- a/src/mongo/db/catalog/validate_adaptor.h
+++ b/src/mongo/db/catalog/validate_adaptor.h
@@ -93,6 +93,7 @@ public:
const RecordId& firstRecordId,
const std::unique_ptr<SeekableRecordCursor>& traverseRecordStoreCursor,
const std::unique_ptr<SeekableRecordCursor>& seekRecordStoreCursor,
+ bool background,
ValidateResults* results,
BSONObjBuilder* output);