1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 #pragma once 7 #include <cassert> 8 #include <unordered_map> 9 #include "port/port.h" 10 #include "rocksdb/file_checksum.h" 11 #include "rocksdb/status.h" 12 #include "util/crc32c.h" 13 #include "util/string_util.h" 14 15 namespace ROCKSDB_NAMESPACE { 16 17 // This is the class to generate the file checksum based on Crc32. It 18 // will be used as the default checksum method for SST file checksum 19 class FileChecksumGenCrc32c : public FileChecksumGenerator { 20 public: FileChecksumGenCrc32c(const FileChecksumGenContext &)21 FileChecksumGenCrc32c(const FileChecksumGenContext& /*context*/) { 22 checksum_ = 0; 23 } 24 Update(const char * data,size_t n)25 void Update(const char* data, size_t n) override { 26 checksum_ = crc32c::Extend(checksum_, data, n); 27 } 28 Finalize()29 void Finalize() override { checksum_str_ = Uint32ToString(checksum_); } 30 GetChecksum()31 std::string GetChecksum() const override { return checksum_str_; } 32 Name()33 const char* Name() const override { return "FileChecksumCrc32c"; } 34 35 // Convert a uint32_t type data into a 4 bytes string. Uint32ToString(uint32_t v)36 static std::string Uint32ToString(uint32_t v) { 37 std::string s; 38 if (port::kLittleEndian) { 39 s.append(reinterpret_cast<char*>(&v), sizeof(v)); 40 } else { 41 char buf[sizeof(v)]; 42 buf[0] = v & 0xff; 43 buf[1] = (v >> 8) & 0xff; 44 buf[2] = (v >> 16) & 0xff; 45 buf[3] = (v >> 24) & 0xff; 46 s.append(buf, sizeof(v)); 47 } 48 size_t i = 0, j = s.size() - 1; 49 while (i < j) { 50 char tmp = s[i]; 51 s[i] = s[j]; 52 s[j] = tmp; 53 ++i; 54 --j; 55 } 56 return s; 57 } 58 59 // Convert a 4 bytes size string into a uint32_t type data. StringToUint32(std::string s)60 static uint32_t StringToUint32(std::string s) { 61 assert(s.size() == sizeof(uint32_t)); 62 size_t i = 0, j = s.size() - 1; 63 while (i < j) { 64 char tmp = s[i]; 65 s[i] = s[j]; 66 s[j] = tmp; 67 ++i; 68 --j; 69 } 70 uint32_t v = 0; 71 if (port::kLittleEndian) { 72 memcpy(&v, s.c_str(), sizeof(uint32_t)); 73 } else { 74 const char* buf = s.c_str(); 75 v |= static_cast<uint32_t>(buf[0]); 76 v |= (static_cast<uint32_t>(buf[1]) << 8); 77 v |= (static_cast<uint32_t>(buf[2]) << 16); 78 v |= (static_cast<uint32_t>(buf[3]) << 24); 79 } 80 return v; 81 } 82 83 private: 84 uint32_t checksum_; 85 std::string checksum_str_; 86 }; 87 88 class FileChecksumGenCrc32cFactory : public FileChecksumGenFactory { 89 public: CreateFileChecksumGenerator(const FileChecksumGenContext & context)90 std::unique_ptr<FileChecksumGenerator> CreateFileChecksumGenerator( 91 const FileChecksumGenContext& context) override { 92 return std::unique_ptr<FileChecksumGenerator>( 93 new FileChecksumGenCrc32c(context)); 94 } 95 Name()96 const char* Name() const override { return "FileChecksumGenCrc32cFactory"; } 97 }; 98 99 // The default implementaion of FileChecksumList 100 class FileChecksumListImpl : public FileChecksumList { 101 public: FileChecksumListImpl()102 FileChecksumListImpl() {} 103 void reset() override; 104 105 size_t size() const override; 106 107 Status GetAllFileChecksums( 108 std::vector<uint64_t>* file_numbers, std::vector<std::string>* checksums, 109 std::vector<std::string>* checksum_func_names) override; 110 111 Status SearchOneFileChecksum(uint64_t file_number, std::string* checksum, 112 std::string* checksum_func_name) override; 113 114 Status InsertOneFileChecksum(uint64_t file_number, 115 const std::string& checksum, 116 const std::string& checksum_func_name) override; 117 118 Status RemoveOneFileChecksum(uint64_t file_number) override; 119 120 private: 121 // Key is the file number, the first portion of the value is checksum, the 122 // second portion of the value is checksum function name. 123 std::unordered_map<uint64_t, std::pair<std::string, std::string>> 124 checksum_map_; 125 }; 126 127 } // namespace ROCKSDB_NAMESPACE 128