summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Hausman <richard.hausman@mongodb.com>2022-07-12 18:35:54 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-07-12 19:06:11 +0000
commit968c499428b57930c64bf1bba9e796f6328582af (patch)
tree492cfb538f55b4d36cad388f2e7d37daa9b456f5 /src
parent54d6cd95aa4a3200eaaa13a4381c00479714c907 (diff)
downloadmongo-968c499428b57930c64bf1bba9e796f6328582af.tar.gz
SERVER-66986 Added check for equivalence of OID-embedded timestamp and 'control.min.timeField' timestamp.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/validate_adaptor.cpp34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/mongo/db/catalog/validate_adaptor.cpp b/src/mongo/db/catalog/validate_adaptor.cpp
index b6e36df4e59..e9206c181be 100644
--- a/src/mongo/db/catalog/validate_adaptor.cpp
+++ b/src/mongo/db/catalog/validate_adaptor.cpp
@@ -136,10 +136,35 @@ void schemaValidationFailed(CollectionValidation::ValidateState* state,
results->valid = false;
}
}
+
+// Checks if the embedded timestamp in the bucket id field matches that in the 'control.min' field.
+Status _validateTimeSeriesIdTimestamp(const CollectionPtr& collection, const BSONObj& recordBson) {
+ // Compares both timestamps measured in seconds.
+ int64_t minTimestamp = recordBson.getField(timeseries::kBucketControlFieldName)
+ .Obj()
+ .getField(timeseries::kBucketControlMinFieldName)
+ .Obj()
+ .getField(collection->getTimeseriesOptions()->getTimeField())
+ .timestamp()
+ .asInt64() /
+ 1000;
+ int64_t oidEmbeddedTimestamp =
+ recordBson.getField(timeseries::kBucketIdFieldName).OID().getTimestamp();
+ if (minTimestamp != oidEmbeddedTimestamp) {
+ return Status(
+ ErrorCodes::InvalidIdField,
+ fmt::format("Mismatch between the embedded timestamp {} in the time-series "
+ "bucket '_id' field and the timestamp {} in 'control.min' field.",
+ Date_t::fromMillisSinceEpoch(oidEmbeddedTimestamp * 1000).toString(),
+ Date_t::fromMillisSinceEpoch(minTimestamp * 1000).toString()));
+ }
+ return Status::OK();
+}
+
/**
* Checks the value of the bucket's version and if it matches the types of the data fields.
*/
-Status _validateTimeSeriesBucketRecord(const RecordId& recordId,
+Status _validateTimeSeriesBucketRecord(const CollectionPtr& collection,
const BSONObj& recordBson,
ValidateResults* results) {
int controlVersion = recordBson.getField(timeseries::kBucketControlFieldName)
@@ -153,7 +178,7 @@ Status _validateTimeSeriesBucketRecord(const RecordId& recordId,
controlVersion));
}
auto dataType = controlVersion == 1 ? BSONType::Object : BSONType::BinData;
- // In addition to checking dataType, make sure that closed buckets have BinData Column subtype
+ // In addition to checking dataType, make sure that closed buckets have BinData Column subtype.
auto isCorrectType = [&](BSONElement el) {
if (controlVersion == 1) {
return el.type() == BSONType::Object;
@@ -172,6 +197,9 @@ Status _validateTimeSeriesBucketRecord(const RecordId& recordId,
mongo::typeName(e.type())));
}
}
+ if (Status status = _validateTimeSeriesIdTimestamp(collection, recordBson); !status.isOK()) {
+ return status;
+ }
return Status::OK();
}
@@ -698,7 +726,7 @@ void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx,
coll->getTimeseriesOptions()) {
// Checks for time-series collection consistency.
Status bucketStatus =
- _validateTimeSeriesBucketRecord(record->id, record->data.toBson(), results);
+ _validateTimeSeriesBucketRecord(coll, record->data.toBson(), results);
// This log id should be kept in sync with the associated warning messages that are
// returned to the client.