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 FileChecksumFuncCrc32c : public FileChecksumFunc { 20 public: Extend(const std::string & init_checksum,const char * data,size_t n)21 std::string Extend(const std::string& init_checksum, const char* data, 22 size_t n) override { 23 assert(data != nullptr); 24 uint32_t checksum_value = StringToUint32(init_checksum); 25 return Uint32ToString(crc32c::Extend(checksum_value, data, n)); 26 } 27 Value(const char * data,size_t n)28 std::string Value(const char* data, size_t n) override { 29 assert(data != nullptr); 30 return Uint32ToString(crc32c::Value(data, n)); 31 } 32 ProcessChecksum(const std::string & checksum)33 std::string ProcessChecksum(const std::string& checksum) override { 34 uint32_t checksum_value = StringToUint32(checksum); 35 return Uint32ToString(crc32c::Mask(checksum_value)); 36 } 37 Name()38 const char* Name() const override { return "FileChecksumCrc32c"; } 39 40 // Convert a uint32_t type data into a 4 bytes string. Uint32ToString(uint32_t v)41 static std::string Uint32ToString(uint32_t v) { 42 std::string s; 43 if (port::kLittleEndian) { 44 s.append(reinterpret_cast<char*>(&v), sizeof(v)); 45 } else { 46 char buf[sizeof(v)]; 47 buf[0] = v & 0xff; 48 buf[1] = (v >> 8) & 0xff; 49 buf[2] = (v >> 16) & 0xff; 50 buf[3] = (v >> 24) & 0xff; 51 s.append(buf, sizeof(v)); 52 } 53 size_t i = 0, j = s.size() - 1; 54 while (i < j) { 55 char tmp = s[i]; 56 s[i] = s[j]; 57 s[j] = tmp; 58 ++i; 59 --j; 60 } 61 return s; 62 } 63 64 // Convert a 4 bytes size string into a uint32_t type data. StringToUint32(std::string s)65 static uint32_t StringToUint32(std::string s) { 66 assert(s.size() == sizeof(uint32_t)); 67 size_t i = 0, j = s.size() - 1; 68 while (i < j) { 69 char tmp = s[i]; 70 s[i] = s[j]; 71 s[j] = tmp; 72 ++i; 73 --j; 74 } 75 uint32_t v = 0; 76 if (port::kLittleEndian) { 77 memcpy(&v, s.c_str(), sizeof(uint32_t)); 78 } else { 79 const char* buf = s.c_str(); 80 v |= static_cast<uint32_t>(buf[0]); 81 v |= (static_cast<uint32_t>(buf[1]) << 8); 82 v |= (static_cast<uint32_t>(buf[2]) << 16); 83 v |= (static_cast<uint32_t>(buf[3]) << 24); 84 } 85 return v; 86 } 87 }; 88 89 // The default implementaion of FileChecksumList 90 class FileChecksumListImpl : public FileChecksumList { 91 public: FileChecksumListImpl()92 FileChecksumListImpl() {} 93 void reset() override; 94 95 size_t size() const override; 96 97 Status GetAllFileChecksums( 98 std::vector<uint64_t>* file_numbers, std::vector<std::string>* checksums, 99 std::vector<std::string>* checksum_func_names) override; 100 101 Status SearchOneFileChecksum(uint64_t file_number, std::string* checksum, 102 std::string* checksum_func_name) override; 103 104 Status InsertOneFileChecksum(uint64_t file_number, 105 const std::string& checksum, 106 const std::string& checksum_func_name) override; 107 108 Status RemoveOneFileChecksum(uint64_t file_number) override; 109 110 private: 111 // Key is the file number, the first portion of the value is checksum, the 112 // second portion of the value is checksum function name. 113 std::unordered_map<uint64_t, std::pair<std::string, std::string>> 114 checksum_map_; 115 }; 116 117 } // namespace ROCKSDB_NAMESPACE 118