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