diff --git a/db/log_format.h b/db/log_format.h index a976b3f9eab3..2dc548d1dd52 100644 --- a/db/log_format.h +++ b/db/log_format.h @@ -17,7 +17,7 @@ namespace ROCKSDB_NAMESPACE { namespace log { -enum RecordType { +enum RecordType : int { // Zero is reserved for preallocated files kZeroType = 0, kFullType = 1, @@ -39,8 +39,11 @@ enum RecordType { // User-defined timestamp sizes kUserDefinedTimestampSizeType = 10, kRecyclableUserDefinedTimestampSizeType = 11, + + // Reserve kRecordTypeSafeIgnoreMask = 32 }; -constexpr int kMaxRecordType = kRecyclableUserDefinedTimestampSizeType; +const int kRecordTypeSafeIgnoreMask = 1 << 5; +constexpr int kMaxRecordType = kRecordTypeSafeIgnoreMask + 5; constexpr unsigned int kBlockSize = 32768; diff --git a/db/log_reader.cc b/db/log_reader.cc index 0cea2183348e..ca06f3c080a7 100644 --- a/db/log_reader.cc +++ b/db/log_reader.cc @@ -313,11 +313,13 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch, break; default: { - std::string reason = - "unknown record type " + std::to_string(record_type); - ReportCorruption( - (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), - reason.c_str()); + if (record_type <= kRecordTypeSafeIgnoreMask) { + std::string reason = + "unknown record type " + std::to_string(record_type); + ReportCorruption( + (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), + reason.c_str()); + } in_fragmented_record = false; scratch->clear(); break; @@ -781,11 +783,13 @@ bool FragmentBufferedReader::ReadRecord(Slice* record, std::string* scratch, break; default: { - std::string reason = - "unknown record type " + std::to_string(fragment_type_or_err); - ReportCorruption( - fragment.size() + (in_fragmented_record_ ? fragments_.size() : 0), - reason.c_str()); + if (fragment_type_or_err <= kRecordTypeSafeIgnoreMask) { + std::string reason = + "unknown record type " + std::to_string(fragment_type_or_err); + ReportCorruption( + fragment.size() + (in_fragmented_record_ ? fragments_.size() : 0), + reason.c_str()); + } in_fragmented_record_ = false; fragments_.clear(); break; diff --git a/db/log_test.cc b/db/log_test.cc index 51f88ac5b7d1..a6bb634fc0f3 100644 --- a/db/log_test.cc +++ b/db/log_test.cc @@ -426,14 +426,14 @@ TEST_P(LogTest, ReadError) { ASSERT_EQ("OK", MatchError("read error")); } -TEST_P(LogTest, BadRecordType) { +TEST_P(LogTest, ForwardCompatibleType) { Write("foo"); // Type is stored in header[6] IncrementByte(6, 100); FixChecksum(0, 3, false); ASSERT_EQ("EOF", Read()); - ASSERT_EQ(3U, DroppedBytes()); - ASSERT_EQ("OK", MatchError("unknown record type")); + ASSERT_EQ(0U, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); } TEST_P(LogTest, TruncatedTrailingRecordIsIgnored) {