summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorYuhong Zhang <yuhong.zhang@mongodb.com>2022-07-26 17:41:34 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-07-26 19:44:51 +0000
commit7ed415c9c79e1e603213d0e88b5ae577e3409b4a (patch)
treee089c53f7b5b2dbb7b73c4ff9465192f4e6031d7 /src/mongo
parent3a91ec210628f1d77251c54ffcd5c1e97dd9f534 (diff)
downloadmongo-7ed415c9c79e1e603213d0e88b5ae577e3409b4a.tar.gz
SERVER-68259 Introduce `NonConformantBSON` error code to differentiate new inconsistencies
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/base/error_codes.yml1
-rw-r--r--src/mongo/db/catalog/validate_adaptor.cpp41
-rw-r--r--src/mongo/db/catalog/validate_adaptor.h1
-rw-r--r--src/mongo/db/catalog/validate_state.h23
4 files changed, 53 insertions, 13 deletions
diff --git a/src/mongo/base/error_codes.yml b/src/mongo/base/error_codes.yml
index 903a8921b23..67d05e909bb 100644
--- a/src/mongo/base/error_codes.yml
+++ b/src/mongo/base/error_codes.yml
@@ -487,6 +487,7 @@ error_codes:
- {code: 375, name: TransactionAPIMustRetryCommit, categories: [InternalOnly]}
- {code: 376, name: ChangeStreamNotEnabled}
- {code: 377, name: FLEMaxTagLimitExceeded }
+ - {code: 378, name: NonConformantBSON, categories: [ValidationError]}
# Error codes 4000-8999 are reserved.
diff --git a/src/mongo/db/catalog/validate_adaptor.cpp b/src/mongo/db/catalog/validate_adaptor.cpp
index 473ba784fb7..20ca1036537 100644
--- a/src/mongo/db/catalog/validate_adaptor.cpp
+++ b/src/mongo/db/catalog/validate_adaptor.cpp
@@ -82,6 +82,9 @@ static constexpr const char* kSchemaValidationFailedReason =
static constexpr const char* kTimeseriesValidationInconsistencyReason =
"Detected one or more documents in this collection incompatible with time-series "
"specifications. For more info, see logs with log id 6698300.";
+static constexpr const char* kBSONValidationNonConformantReason =
+ "Detected one or more documents in this collection not conformant to BSON specifications. For "
+ "more info, see logs with log id 6825900";
/**
* Validate that for each record in a clustered RecordStore the record key (RecordId) matches the
@@ -319,19 +322,42 @@ void _timeseriesValidationFailed(CollectionValidation::ValidateState* state,
results->warnings.push_back(kTimeseriesValidationInconsistencyReason);
}
+
+void _BSONSpecValidationFailed(CollectionValidation::ValidateState* state,
+ ValidateResults* results) {
+ if (state->isBSONDataNonConformant()) {
+ // Only report the warning message once.
+ return;
+ }
+ state->setBSONDataNonConformant();
+
+ results->warnings.push_back(kBSONValidationNonConformantReason);
+}
} // namespace
Status ValidateAdaptor::validateRecord(OperationContext* opCtx,
const RecordId& recordId,
const RecordData& record,
+ long long* nNonCompliantDocuments,
size_t* dataSize,
ValidateResults* results) {
- auto validateBSONMode = _validateState->isCheckingBSONConsistencies()
- ? BSONValidateMode::kFull
- : BSONValidateMode::kExtended;
+ auto validateBSONMode = BSONValidateMode::kDefault;
+ if (serverGlobalParams.featureCompatibility.isVersionInitialized() &&
+ feature_flags::gExtendValidateCommand.isEnabled(serverGlobalParams.featureCompatibility)) {
+ validateBSONMode = _validateState->getBSONValidateMode();
+ }
const Status status = validateBSON(record.data(), record.size(), validateBSONMode);
- if (!status.isOK())
- return status;
+ if (!status.isOK()) {
+ if (status.code() != ErrorCodes::NonConformantBSON) {
+ return status;
+ }
+ LOGV2_WARNING(6825900,
+ "Document is not conformant to BSON specifications",
+ "recordId"_attr = recordId,
+ "reason"_attr = status);
+ (*nNonCompliantDocuments)++;
+ _BSONSpecValidationFailed(_validateState, results);
+ }
BSONObj recordBson = record.toBson();
*dataSize = recordBson.objsize();
@@ -466,7 +492,7 @@ Status ValidateAdaptor::validateRecord(OperationContext* opCtx,
}
}
}
- return status;
+ return Status::OK();
}
namespace {
@@ -762,7 +788,8 @@ void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx,
interruptIntervalNumBytes += dataSize;
dataSizeTotal += dataSize;
size_t validatedSize = 0;
- Status status = validateRecord(opCtx, record->id, record->data, &validatedSize, results);
+ Status status = validateRecord(
+ opCtx, record->id, record->data, &nNonCompliantDocuments, &validatedSize, results);
// RecordStores are required to return records in RecordId order.
if (prevRecordId.isValid()) {
diff --git a/src/mongo/db/catalog/validate_adaptor.h b/src/mongo/db/catalog/validate_adaptor.h
index ba548ca6358..3217c7b5824 100644
--- a/src/mongo/db/catalog/validate_adaptor.h
+++ b/src/mongo/db/catalog/validate_adaptor.h
@@ -56,6 +56,7 @@ public:
virtual Status validateRecord(OperationContext* opCtx,
const RecordId& recordId,
const RecordData& record,
+ long long* nNonCompliantDocuments,
size_t* dataSize,
ValidateResults* results);
diff --git a/src/mongo/db/catalog/validate_state.h b/src/mongo/db/catalog/validate_state.h
index 9a3aef7a943..fb4d85eb9a3 100644
--- a/src/mongo/db/catalog/validate_state.h
+++ b/src/mongo/db/catalog/validate_state.h
@@ -90,12 +90,14 @@ public:
return isFullValidation() || _mode == ValidateMode::kForegroundFullIndexOnly;
}
- bool isCheckingBSONConsistencies() const {
+ BSONValidateMode getBSONValidateMode() const {
return serverGlobalParams.featureCompatibility.isVersionInitialized() &&
- feature_flags::gExtendValidateCommand.isEnabled(
- serverGlobalParams.featureCompatibility) &&
- (_mode == ValidateMode::kForegroundCheckBSON ||
- _mode == ValidateMode::kBackgroundCheckBSON || isFullValidation());
+ feature_flags::gExtendValidateCommand.isEnabled(
+ serverGlobalParams.featureCompatibility) &&
+ (_mode == ValidateMode::kForegroundCheckBSON ||
+ _mode == ValidateMode::kBackgroundCheckBSON || isFullValidation())
+ ? BSONValidateMode::kFull
+ : BSONValidateMode::kExtended;
}
bool isCollectionSchemaViolated() const {
@@ -106,13 +108,21 @@ public:
_collectionSchemaViolated = true;
}
- bool isTimeseriesDataInconsistent() {
+ bool isTimeseriesDataInconsistent() const {
return _timeseriesDataInconsistency;
}
void setTimeseriesDataInconsistent() {
_timeseriesDataInconsistency = true;
}
+ bool isBSONDataNonConformant() const {
+ return _BSONDataNonConformant;
+ }
+
+ void setBSONDataNonConformant() {
+ _BSONDataNonConformant = true;
+ }
+
bool fixErrors() const {
return _repairMode == RepairMode::kFixErrors;
}
@@ -229,6 +239,7 @@ private:
RepairMode _repairMode;
bool _collectionSchemaViolated = false;
bool _timeseriesDataInconsistency = false;
+ bool _BSONDataNonConformant = false;
boost::optional<ShouldNotConflictWithSecondaryBatchApplicationBlock> _noPBWM;
boost::optional<Lock::GlobalLock> _globalLock;