]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
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). | |
7c673cae FG |
5 | // |
6 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. | |
7 | // Use of this source code is governed by a BSD-style license that can be | |
8 | // found in the LICENSE file. See the AUTHORS file for names of contributors. | |
9 | #include "db/dbformat.h" | |
10 | ||
7c673cae | 11 | #include <stdio.h> |
1e59de90 | 12 | |
f67539c2 | 13 | #include <cinttypes> |
1e59de90 TL |
14 | |
15 | #include "db/lookup_key.h" | |
7c673cae FG |
16 | #include "monitoring/perf_context_imp.h" |
17 | #include "port/port.h" | |
18 | #include "util/coding.h" | |
19 | #include "util/string_util.h" | |
20 | ||
f67539c2 | 21 | namespace ROCKSDB_NAMESPACE { |
7c673cae FG |
22 | |
23 | // kValueTypeForSeek defines the ValueType that should be passed when | |
24 | // constructing a ParsedInternalKey object for seeking to a particular | |
25 | // sequence number (since we sort sequence numbers in decreasing order | |
26 | // and the value type is embedded as the low 8 bits in the sequence | |
27 | // number in internal keys, we need to use the highest-numbered | |
28 | // ValueType, not the lowest). | |
1e59de90 | 29 | const ValueType kValueTypeForSeek = kTypeWideColumnEntity; |
7c673cae | 30 | const ValueType kValueTypeForSeekForPrev = kTypeDeletion; |
1e59de90 | 31 | const std::string kDisableUserTimestamp(""); |
7c673cae | 32 | |
11fdf7f2 TL |
33 | EntryType GetEntryType(ValueType value_type) { |
34 | switch (value_type) { | |
35 | case kTypeValue: | |
36 | return kEntryPut; | |
37 | case kTypeDeletion: | |
38 | return kEntryDelete; | |
20effc67 TL |
39 | case kTypeDeletionWithTimestamp: |
40 | return kEntryDeleteWithTimestamp; | |
11fdf7f2 TL |
41 | case kTypeSingleDeletion: |
42 | return kEntrySingleDelete; | |
43 | case kTypeMerge: | |
44 | return kEntryMerge; | |
45 | case kTypeRangeDeletion: | |
46 | return kEntryRangeDeletion; | |
47 | case kTypeBlobIndex: | |
48 | return kEntryBlobIndex; | |
1e59de90 TL |
49 | case kTypeWideColumnEntity: |
50 | return kEntryWideColumnEntity; | |
11fdf7f2 TL |
51 | default: |
52 | return kEntryOther; | |
53 | } | |
54 | } | |
55 | ||
7c673cae FG |
56 | void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { |
57 | result->append(key.user_key.data(), key.user_key.size()); | |
58 | PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); | |
59 | } | |
60 | ||
20effc67 TL |
61 | void AppendInternalKeyWithDifferentTimestamp(std::string* result, |
62 | const ParsedInternalKey& key, | |
63 | const Slice& ts) { | |
64 | assert(key.user_key.size() >= ts.size()); | |
65 | result->append(key.user_key.data(), key.user_key.size() - ts.size()); | |
66 | result->append(ts.data(), ts.size()); | |
67 | PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); | |
68 | } | |
69 | ||
7c673cae FG |
70 | void AppendInternalKeyFooter(std::string* result, SequenceNumber s, |
71 | ValueType t) { | |
72 | PutFixed64(result, PackSequenceAndType(s, t)); | |
73 | } | |
74 | ||
1e59de90 TL |
75 | void AppendKeyWithMinTimestamp(std::string* result, const Slice& key, |
76 | size_t ts_sz) { | |
77 | assert(ts_sz > 0); | |
78 | const std::string kTsMin(ts_sz, static_cast<unsigned char>(0)); | |
79 | result->append(key.data(), key.size()); | |
80 | result->append(kTsMin.data(), ts_sz); | |
81 | } | |
82 | ||
83 | void AppendKeyWithMaxTimestamp(std::string* result, const Slice& key, | |
84 | size_t ts_sz) { | |
85 | assert(ts_sz > 0); | |
86 | const std::string kTsMax(ts_sz, static_cast<unsigned char>(0xff)); | |
87 | result->append(key.data(), key.size()); | |
88 | result->append(kTsMax.data(), ts_sz); | |
89 | } | |
90 | ||
91 | void AppendUserKeyWithMaxTimestamp(std::string* result, const Slice& key, | |
92 | size_t ts_sz) { | |
93 | assert(ts_sz > 0); | |
94 | result->append(key.data(), key.size() - ts_sz); | |
95 | ||
96 | static constexpr char kTsMax[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff"; | |
97 | if (ts_sz < strlen(kTsMax)) { | |
98 | result->append(kTsMax, ts_sz); | |
99 | } else { | |
100 | result->append(std::string(ts_sz, '\xff')); | |
101 | } | |
102 | } | |
103 | ||
20effc67 TL |
104 | std::string ParsedInternalKey::DebugString(bool log_err_key, bool hex) const { |
105 | std::string result = "'"; | |
106 | if (log_err_key) { | |
107 | result += user_key.ToString(hex); | |
108 | } else { | |
109 | result += "<redacted>"; | |
110 | } | |
111 | ||
7c673cae FG |
112 | char buf[50]; |
113 | snprintf(buf, sizeof(buf), "' seq:%" PRIu64 ", type:%d", sequence, | |
114 | static_cast<int>(type)); | |
20effc67 | 115 | |
7c673cae FG |
116 | result += buf; |
117 | return result; | |
118 | } | |
119 | ||
120 | std::string InternalKey::DebugString(bool hex) const { | |
121 | std::string result; | |
122 | ParsedInternalKey parsed; | |
20effc67 TL |
123 | if (ParseInternalKey(rep_, &parsed, false /* log_err_key */).ok()) { |
124 | result = parsed.DebugString(true /* log_err_key */, hex); // TODO | |
7c673cae FG |
125 | } else { |
126 | result = "(bad)"; | |
127 | result.append(EscapeString(rep_)); | |
128 | } | |
129 | return result; | |
130 | } | |
131 | ||
7c673cae FG |
132 | int InternalKeyComparator::Compare(const ParsedInternalKey& a, |
133 | const ParsedInternalKey& b) const { | |
134 | // Order by: | |
135 | // increasing user key (according to user-supplied comparator) | |
136 | // decreasing sequence number | |
137 | // decreasing type (though sequence# should be enough to disambiguate) | |
494da23a | 138 | int r = user_comparator_.Compare(a.user_key, b.user_key); |
7c673cae FG |
139 | if (r == 0) { |
140 | if (a.sequence > b.sequence) { | |
141 | r = -1; | |
142 | } else if (a.sequence < b.sequence) { | |
143 | r = +1; | |
144 | } else if (a.type > b.type) { | |
145 | r = -1; | |
146 | } else if (a.type < b.type) { | |
147 | r = +1; | |
148 | } | |
149 | } | |
150 | return r; | |
151 | } | |
152 | ||
f67539c2 TL |
153 | LookupKey::LookupKey(const Slice& _user_key, SequenceNumber s, |
154 | const Slice* ts) { | |
7c673cae | 155 | size_t usize = _user_key.size(); |
f67539c2 TL |
156 | size_t ts_sz = (nullptr == ts) ? 0 : ts->size(); |
157 | size_t needed = usize + ts_sz + 13; // A conservative estimate | |
7c673cae FG |
158 | char* dst; |
159 | if (needed <= sizeof(space_)) { | |
160 | dst = space_; | |
161 | } else { | |
162 | dst = new char[needed]; | |
163 | } | |
164 | start_ = dst; | |
165 | // NOTE: We don't support users keys of more than 2GB :) | |
f67539c2 | 166 | dst = EncodeVarint32(dst, static_cast<uint32_t>(usize + ts_sz + 8)); |
7c673cae FG |
167 | kstart_ = dst; |
168 | memcpy(dst, _user_key.data(), usize); | |
169 | dst += usize; | |
f67539c2 TL |
170 | if (nullptr != ts) { |
171 | memcpy(dst, ts->data(), ts_sz); | |
172 | dst += ts_sz; | |
173 | } | |
7c673cae FG |
174 | EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); |
175 | dst += 8; | |
176 | end_ = dst; | |
177 | } | |
178 | ||
11fdf7f2 TL |
179 | void IterKey::EnlargeBuffer(size_t key_size) { |
180 | // If size is smaller than buffer size, continue using current buffer, | |
181 | // or the static allocated one, as default | |
182 | assert(key_size > buf_size_); | |
183 | // Need to enlarge the buffer. | |
184 | ResetBuffer(); | |
185 | buf_ = new char[key_size]; | |
186 | buf_size_ = key_size; | |
187 | } | |
f67539c2 | 188 | } // namespace ROCKSDB_NAMESPACE |