/Users/mcomp/contrib/bitcoin/src/leveldb/db/dbformat.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
4 | | |
5 | | #ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_ |
6 | | #define STORAGE_LEVELDB_DB_DBFORMAT_H_ |
7 | | |
8 | | #include <cstddef> |
9 | | #include <cstdint> |
10 | | #include <string> |
11 | | |
12 | | #include "leveldb/comparator.h" |
13 | | #include "leveldb/db.h" |
14 | | #include "leveldb/filter_policy.h" |
15 | | #include "leveldb/slice.h" |
16 | | #include "leveldb/table_builder.h" |
17 | | #include "util/coding.h" |
18 | | #include "util/logging.h" |
19 | | |
20 | | namespace leveldb { |
21 | | |
22 | | // Grouping of constants. We may want to make some of these |
23 | | // parameters set via options. |
24 | | namespace config { |
25 | | static const int kNumLevels = 7; |
26 | | |
27 | | // Level-0 compaction is started when we hit this many files. |
28 | | static const int kL0_CompactionTrigger = 4; |
29 | | |
30 | | // Soft limit on number of level-0 files. We slow down writes at this point. |
31 | | static const int kL0_SlowdownWritesTrigger = 8; |
32 | | |
33 | | // Maximum number of level-0 files. We stop writes at this point. |
34 | | static const int kL0_StopWritesTrigger = 12; |
35 | | |
36 | | // Maximum level to which a new compacted memtable is pushed if it |
37 | | // does not create overlap. We try to push to level 2 to avoid the |
38 | | // relatively expensive level 0=>1 compactions and to avoid some |
39 | | // expensive manifest file operations. We do not push all the way to |
40 | | // the largest level since that can generate a lot of wasted disk |
41 | | // space if the same key space is being repeatedly overwritten. |
42 | | static const int kMaxMemCompactLevel = 2; |
43 | | |
44 | | // Approximate gap in bytes between samples of data read during iteration. |
45 | | static const int kReadBytesPeriod = 1048576; |
46 | | |
47 | | } // namespace config |
48 | | |
49 | | class InternalKey; |
50 | | |
51 | | // Value types encoded as the last component of internal keys. |
52 | | // DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk |
53 | | // data structures. |
54 | | enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 }; |
55 | | // kValueTypeForSeek defines the ValueType that should be passed when |
56 | | // constructing a ParsedInternalKey object for seeking to a particular |
57 | | // sequence number (since we sort sequence numbers in decreasing order |
58 | | // and the value type is embedded as the low 8 bits in the sequence |
59 | | // number in internal keys, we need to use the highest-numbered |
60 | | // ValueType, not the lowest). |
61 | | static const ValueType kValueTypeForSeek = kTypeValue; |
62 | | |
63 | | typedef uint64_t SequenceNumber; |
64 | | |
65 | | // We leave eight bits empty at the bottom so a type and sequence# |
66 | | // can be packed together into 64-bits. |
67 | | static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1); |
68 | | |
69 | | struct ParsedInternalKey { |
70 | | Slice user_key; |
71 | | SequenceNumber sequence; |
72 | | ValueType type; |
73 | | |
74 | 0 | ParsedInternalKey() {} // Intentionally left uninitialized (for speed) |
75 | | ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) |
76 | 0 | : user_key(u), sequence(seq), type(t) {} |
77 | | std::string DebugString() const; |
78 | | }; |
79 | | |
80 | | // Return the length of the encoding of "key". |
81 | 0 | inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { |
82 | 0 | return key.user_key.size() + 8; |
83 | 0 | } |
84 | | |
85 | | // Append the serialization of "key" to *result. |
86 | | void AppendInternalKey(std::string* result, const ParsedInternalKey& key); |
87 | | |
88 | | // Attempt to parse an internal key from "internal_key". On success, |
89 | | // stores the parsed data in "*result", and returns true. |
90 | | // |
91 | | // On error, returns false, leaves "*result" in an undefined state. |
92 | | bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result); |
93 | | |
94 | | // Returns the user key portion of an internal key. |
95 | 0 | inline Slice ExtractUserKey(const Slice& internal_key) { |
96 | 0 | assert(internal_key.size() >= 8); |
97 | 0 | return Slice(internal_key.data(), internal_key.size() - 8); |
98 | 0 | } |
99 | | |
100 | | // A comparator for internal keys that uses a specified comparator for |
101 | | // the user key portion and breaks ties by decreasing sequence number. |
102 | | class InternalKeyComparator : public Comparator { |
103 | | private: |
104 | | const Comparator* user_comparator_; |
105 | | |
106 | | public: |
107 | 0 | explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {} |
108 | | const char* Name() const override; |
109 | | int Compare(const Slice& a, const Slice& b) const override; |
110 | | void FindShortestSeparator(std::string* start, |
111 | | const Slice& limit) const override; |
112 | | void FindShortSuccessor(std::string* key) const override; |
113 | | |
114 | 0 | const Comparator* user_comparator() const { return user_comparator_; } |
115 | | |
116 | | int Compare(const InternalKey& a, const InternalKey& b) const; |
117 | | }; |
118 | | |
119 | | // Filter policy wrapper that converts from internal keys to user keys |
120 | | class InternalFilterPolicy : public FilterPolicy { |
121 | | private: |
122 | | const FilterPolicy* const user_policy_; |
123 | | |
124 | | public: |
125 | 0 | explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {} |
126 | | const char* Name() const override; |
127 | | void CreateFilter(const Slice* keys, int n, std::string* dst) const override; |
128 | | bool KeyMayMatch(const Slice& key, const Slice& filter) const override; |
129 | | }; |
130 | | |
131 | | // Modules in this directory should keep internal keys wrapped inside |
132 | | // the following class instead of plain strings so that we do not |
133 | | // incorrectly use string comparisons instead of an InternalKeyComparator. |
134 | | class InternalKey { |
135 | | private: |
136 | | std::string rep_; |
137 | | |
138 | | public: |
139 | 0 | InternalKey() {} // Leave rep_ as empty to indicate it is invalid |
140 | 0 | InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { |
141 | 0 | AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); |
142 | 0 | } |
143 | | |
144 | 0 | bool DecodeFrom(const Slice& s) { |
145 | 0 | rep_.assign(s.data(), s.size()); |
146 | 0 | return !rep_.empty(); |
147 | 0 | } |
148 | | |
149 | 0 | Slice Encode() const { |
150 | 0 | assert(!rep_.empty()); |
151 | 0 | return rep_; |
152 | 0 | } |
153 | | |
154 | 0 | Slice user_key() const { return ExtractUserKey(rep_); } |
155 | | |
156 | 0 | void SetFrom(const ParsedInternalKey& p) { |
157 | 0 | rep_.clear(); |
158 | 0 | AppendInternalKey(&rep_, p); |
159 | 0 | } |
160 | | |
161 | 0 | void Clear() { rep_.clear(); } |
162 | | |
163 | | std::string DebugString() const; |
164 | | }; |
165 | | |
166 | | inline int InternalKeyComparator::Compare(const InternalKey& a, |
167 | 0 | const InternalKey& b) const { |
168 | 0 | return Compare(a.Encode(), b.Encode()); |
169 | 0 | } |
170 | | |
171 | | inline bool ParseInternalKey(const Slice& internal_key, |
172 | 0 | ParsedInternalKey* result) { |
173 | 0 | const size_t n = internal_key.size(); |
174 | 0 | if (n < 8) return false; |
175 | 0 | uint64_t num = DecodeFixed64(internal_key.data() + n - 8); |
176 | 0 | uint8_t c = num & 0xff; |
177 | 0 | result->sequence = num >> 8; |
178 | 0 | result->type = static_cast<ValueType>(c); |
179 | 0 | result->user_key = Slice(internal_key.data(), n - 8); |
180 | 0 | return (c <= static_cast<uint8_t>(kTypeValue)); |
181 | 0 | } |
182 | | |
183 | | // A helper class useful for DBImpl::Get() |
184 | | class LookupKey { |
185 | | public: |
186 | | // Initialize *this for looking up user_key at a snapshot with |
187 | | // the specified sequence number. |
188 | | LookupKey(const Slice& user_key, SequenceNumber sequence); |
189 | | |
190 | | LookupKey(const LookupKey&) = delete; |
191 | | LookupKey& operator=(const LookupKey&) = delete; |
192 | | |
193 | | ~LookupKey(); |
194 | | |
195 | | // Return a key suitable for lookup in a MemTable. |
196 | 0 | Slice memtable_key() const { return Slice(start_, end_ - start_); } |
197 | | |
198 | | // Return an internal key (suitable for passing to an internal iterator) |
199 | 0 | Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } |
200 | | |
201 | | // Return the user key |
202 | 0 | Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } |
203 | | |
204 | | private: |
205 | | // We construct a char array of the form: |
206 | | // klength varint32 <-- start_ |
207 | | // userkey char[klength] <-- kstart_ |
208 | | // tag uint64 |
209 | | // <-- end_ |
210 | | // The array is a suitable MemTable key. |
211 | | // The suffix starting with "userkey" can be used as an InternalKey. |
212 | | const char* start_; |
213 | | const char* kstart_; |
214 | | const char* end_; |
215 | | char space_[200]; // Avoid allocation for short keys |
216 | | }; |
217 | | |
218 | 0 | inline LookupKey::~LookupKey() { |
219 | 0 | if (start_ != space_) delete[] start_; |
220 | 0 | } |
221 | | |
222 | | } // namespace leveldb |
223 | | |
224 | | #endif // STORAGE_LEVELDB_DB_DBFORMAT_H_ |