1818#include < cstdio>
1919#include < map>
2020#include < set>
21+ #include < sstream>
2122#include < stdexcept>
2223#include < string>
2324#include < unordered_map>
@@ -4725,8 +4726,29 @@ Status DBImpl::CreateColumnFamilyWithImport(
47254726 return status;
47264727}
47274728
4729+ Status DBImpl::VerifyFileChecksums (const ReadOptions& read_options) {
4730+ return VerifyChecksumInternal (read_options, /* use_file_checksum=*/ true );
4731+ }
4732+
47284733Status DBImpl::VerifyChecksum (const ReadOptions& read_options) {
4734+ return VerifyChecksumInternal (read_options, /* use_file_checksum=*/ false );
4735+ }
4736+
4737+ Status DBImpl::VerifyChecksumInternal (const ReadOptions& read_options,
4738+ bool use_file_checksum) {
47294739 Status s;
4740+
4741+ if (use_file_checksum) {
4742+ FileChecksumGenFactory* const file_checksum_gen_factory =
4743+ immutable_db_options_.file_checksum_gen_factory .get ();
4744+ if (!file_checksum_gen_factory) {
4745+ s = Status::InvalidArgument (
4746+ " Cannot verify file checksum if options.file_checksum_gen_factory is "
4747+ " null" );
4748+ return s;
4749+ }
4750+ }
4751+
47304752 std::vector<ColumnFamilyData*> cfd_list;
47314753 {
47324754 InstrumentedMutexLock l (&mutex_);
@@ -4741,23 +4763,31 @@ Status DBImpl::VerifyChecksum(const ReadOptions& read_options) {
47414763 for (auto cfd : cfd_list) {
47424764 sv_list.push_back (cfd->GetReferencedSuperVersion (this ));
47434765 }
4766+
47444767 for (auto & sv : sv_list) {
47454768 VersionStorageInfo* vstorage = sv->current ->storage_info ();
47464769 ColumnFamilyData* cfd = sv->current ->cfd ();
47474770 Options opts;
4748- {
4771+ if (!use_file_checksum) {
47494772 InstrumentedMutexLock l (&mutex_);
47504773 opts = Options (BuildDBOptions (immutable_db_options_, mutable_db_options_),
47514774 cfd->GetLatestCFOptions ());
47524775 }
47534776 for (int i = 0 ; i < vstorage->num_non_empty_levels () && s.ok (); i++) {
47544777 for (size_t j = 0 ; j < vstorage->LevelFilesBrief (i).num_files && s.ok ();
47554778 j++) {
4756- const auto & fd = vstorage->LevelFilesBrief (i).files [j].fd ;
4779+ const auto & fd_with_krange = vstorage->LevelFilesBrief (i).files [j];
4780+ const auto & fd = fd_with_krange.fd ;
4781+ const FileMetaData* fmeta = fd_with_krange.file_metadata ;
4782+ assert (fmeta);
47574783 std::string fname = TableFileName (cfd->ioptions ()->cf_paths ,
47584784 fd.GetNumber (), fd.GetPathId ());
4759- s = ROCKSDB_NAMESPACE::VerifySstFileChecksum (opts, file_options_,
4760- read_options, fname);
4785+ if (use_file_checksum) {
4786+ s = VerifySstFileChecksum (*fmeta, fname, read_options);
4787+ } else {
4788+ s = ROCKSDB_NAMESPACE::VerifySstFileChecksum (opts, file_options_,
4789+ read_options, fname);
4790+ }
47614791 }
47624792 }
47634793 if (!s.ok ()) {
@@ -4788,6 +4818,34 @@ Status DBImpl::VerifyChecksum(const ReadOptions& read_options) {
47884818 return s;
47894819}
47904820
4821+ Status DBImpl::VerifySstFileChecksum (const FileMetaData& fmeta,
4822+ const std::string& fname,
4823+ const ReadOptions& read_options) {
4824+ Status s;
4825+ if (fmeta.file_checksum == kUnknownFileChecksum ) {
4826+ return s;
4827+ }
4828+ std::string file_checksum;
4829+ std::string func_name;
4830+ s = ROCKSDB_NAMESPACE::GenerateOneFileChecksum (
4831+ fs_.get (), fname, immutable_db_options_.file_checksum_gen_factory .get (),
4832+ fmeta.file_checksum_func_name , &file_checksum, &func_name,
4833+ read_options.readahead_size , immutable_db_options_.allow_mmap_reads ,
4834+ io_tracer_);
4835+ if (s.ok ()) {
4836+ assert (fmeta.file_checksum_func_name == func_name);
4837+ if (file_checksum != fmeta.file_checksum ) {
4838+ std::ostringstream oss;
4839+ oss << fname << " file checksum mismatch, " ;
4840+ oss << " expecting " << Slice (fmeta.file_checksum ).ToString (/* hex=*/ true );
4841+ oss << " , but actual " << Slice (file_checksum).ToString (/* hex=*/ true );
4842+ s = Status::Corruption (oss.str ());
4843+ TEST_SYNC_POINT_CALLBACK (" DBImpl::VerifySstFileChecksum:mismatch" , &s);
4844+ }
4845+ }
4846+ return s;
4847+ }
4848+
47914849void DBImpl::NotifyOnExternalFileIngested (
47924850 ColumnFamilyData* cfd, const ExternalSstFileIngestionJob& ingestion_job) {
47934851 if (immutable_db_options_.listeners .empty ()) {
0 commit comments