From d7277aec3e480ab6f6a3ff74a12dbdf1eb635081 Mon Sep 17 00:00:00 2001 From: Georges Berenger Date: Thu, 8 Aug 2024 16:37:38 -0700 Subject: [PATCH] Sort records fully for checksums Summary: When reading a VRS file, records are sorted by timestamp, streamID, and position in the file, but not by record type, which means that two files can have the same records, but in slightly different order, and not be equivalent for checksums. As we added the `sort_records` option to generate file that might not be fully sorted, it's easy to generate file that are equivalent, but have different checksums. When opening a file, you can now specify the same `sort_records` options to get the file fully sorted, taking into account the record's type, to get a deterministic state. Reviewed By: kiminoue7 Differential Revision: D60942282 fbshipit-source-id: cdf94109f29ea794f0cedafc0655e38873123045 --- vrs/RecordFileReader.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/vrs/RecordFileReader.cpp b/vrs/RecordFileReader.cpp index be607cd2..31f75b09 100644 --- a/vrs/RecordFileReader.cpp +++ b/vrs/RecordFileReader.cpp @@ -43,6 +43,30 @@ using namespace std; +namespace { + +using namespace vrs; + +bool before(Record::Type lhs, Record::Type rhs) { + if (lhs == Record::Type::CONFIGURATION && rhs == Record::Type::STATE) { + return true; + } else if (lhs == Record::Type::STATE && rhs == Record::Type::CONFIGURATION) { + return false; + } + return static_cast(lhs) < static_cast(rhs); +} + +bool fullRecordCompare(const IndexRecord::RecordInfo& lhs, const IndexRecord::RecordInfo& rhs) { + return lhs.timestamp < rhs.timestamp || + (lhs.timestamp <= rhs.timestamp && + (lhs.streamId < rhs.streamId || + (lhs.streamId == rhs.streamId && + (before(lhs.recordType, rhs.recordType) || + (lhs.recordType == rhs.recordType && lhs.fileOffset < rhs.fileOffset))))); +} + +} // namespace + namespace vrs { StreamPlayer::~StreamPlayer() = default; @@ -311,6 +335,9 @@ int RecordFileReader::doOpenFile( streamRecordCounts_[record.streamId][record.recordType]++; } } + if (error == 0 && fileSpec.getExtraAsBool("sort_records", false)) { + sort(recordIndex_.begin(), recordIndex_.end(), fullRecordCompare); + } return error; }