diff options
author | Yuhong Zhang <yuhong.zhang@mongodb.com> | 2022-07-26 17:41:34 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-07-26 19:44:51 +0000 |
commit | 7ed415c9c79e1e603213d0e88b5ae577e3409b4a (patch) | |
tree | e089c53f7b5b2dbb7b73c4ff9465192f4e6031d7 /src/mongo | |
parent | 3a91ec210628f1d77251c54ffcd5c1e97dd9f534 (diff) | |
download | mongo-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.yml | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_adaptor.cpp | 41 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_adaptor.h | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_state.h | 23 |
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; |