/src/rocksdb/table/plain/plain_table_key_coding.h
Line | Count | Source |
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 | | |
8 | | #include <array> |
9 | | |
10 | | #include "rocksdb/slice.h" |
11 | | #include "table/plain/plain_table_reader.h" |
12 | | |
13 | | // The file contains three helper classes of PlainTable format, |
14 | | // PlainTableKeyEncoder, PlainTableKeyDecoder and PlainTableFileReader. |
15 | | // These classes issue the lowest level of operations of PlainTable. |
16 | | // Actual data format of the key is documented in comments of class |
17 | | // PlainTableFactory. |
18 | | namespace ROCKSDB_NAMESPACE { |
19 | | |
20 | | class WritableFile; |
21 | | struct ParsedInternalKey; |
22 | | struct PlainTableReaderFileInfo; |
23 | | enum PlainTableEntryType : unsigned char; |
24 | | |
25 | | // Helper class for PlainTable format to write out a key to an output file |
26 | | // The class is used in PlainTableBuilder. |
27 | | class PlainTableKeyEncoder { |
28 | | public: |
29 | | explicit PlainTableKeyEncoder(EncodingType encoding_type, |
30 | | uint32_t user_key_len, |
31 | | const SliceTransform* prefix_extractor, |
32 | | size_t index_sparseness) |
33 | 0 | : encoding_type_((prefix_extractor != nullptr) ? encoding_type : kPlain), |
34 | 0 | fixed_user_key_len_(user_key_len), |
35 | 0 | prefix_extractor_(prefix_extractor), |
36 | 0 | index_sparseness_((index_sparseness > 1) ? index_sparseness : 1), |
37 | 0 | key_count_for_prefix_(0) {} |
38 | | // key: the key to write out, in the format of internal key. |
39 | | // file: the output file to write out |
40 | | // offset: offset in the file. Needs to be updated after appending bytes |
41 | | // for the key |
42 | | // meta_bytes_buf: buffer for extra meta bytes |
43 | | // meta_bytes_buf_size: offset to append extra meta bytes. Will be updated |
44 | | // if meta_bytes_buf is updated. |
45 | | IOStatus AppendKey(const Slice& key, WritableFileWriter* file, |
46 | | uint64_t* offset, char* meta_bytes_buf, |
47 | | size_t* meta_bytes_buf_size); |
48 | | |
49 | | // Return actual encoding type to be picked |
50 | 0 | EncodingType GetEncodingType() { return encoding_type_; } |
51 | | |
52 | | private: |
53 | | EncodingType encoding_type_; |
54 | | uint32_t fixed_user_key_len_; |
55 | | const SliceTransform* prefix_extractor_; |
56 | | const size_t index_sparseness_; |
57 | | size_t key_count_for_prefix_; |
58 | | IterKey pre_prefix_; |
59 | | }; |
60 | | |
61 | | // The class does raw file reads for PlainTableReader. |
62 | | // It hides whether it is a mmap-read, or a non-mmap read. |
63 | | // The class is implemented in a way to favor the performance of mmap case. |
64 | | // The class is used by PlainTableReader. |
65 | | class PlainTableFileReader { |
66 | | public: |
67 | | explicit PlainTableFileReader(const PlainTableReaderFileInfo* _file_info) |
68 | 0 | : file_info_(_file_info), num_buf_(0) {} |
69 | | |
70 | 0 | ~PlainTableFileReader() { |
71 | | // Should fix. |
72 | 0 | status_.PermitUncheckedError(); |
73 | 0 | } |
74 | | |
75 | | // In mmaped mode, the results point to mmaped area of the file, which |
76 | | // means it is always valid before closing the file. |
77 | | // In non-mmap mode, the results point to an internal buffer. If the caller |
78 | | // makes another read call, the results may not be valid. So callers should |
79 | | // make a copy when needed. |
80 | | // In order to save read calls to files, we keep two internal buffers: |
81 | | // the first read and the most recent read. This is efficient because it |
82 | | // columns these two common use cases: |
83 | | // (1) hash index only identify one location, we read the key to verify |
84 | | // the location, and read key and value if it is the right location. |
85 | | // (2) after hash index checking, we identify two locations (because of |
86 | | // hash bucket conflicts), we binary search the two location to see |
87 | | // which one is what we need and start to read from the location. |
88 | | // These two most common use cases will be covered by the two buffers |
89 | | // so that we don't need to re-read the same location. |
90 | | // Currently we keep a fixed size buffer. If a read doesn't exactly fit |
91 | | // the buffer, we replace the second buffer with the location user reads. |
92 | | // |
93 | | // If return false, status code is stored in status_. |
94 | 0 | bool Read(uint32_t file_offset, uint32_t len, Slice* out) { |
95 | 0 | if (file_info_->is_mmap_mode) { |
96 | 0 | assert(file_offset + len <= file_info_->data_end_offset); |
97 | 0 | *out = Slice(file_info_->file_data.data() + file_offset, len); |
98 | 0 | return true; |
99 | 0 | } else { |
100 | 0 | return ReadNonMmap(file_offset, len, out); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | // If return false, status code is stored in status_. |
105 | | bool ReadNonMmap(uint32_t file_offset, uint32_t len, Slice* output); |
106 | | |
107 | | // *bytes_read = 0 means eof. false means failure and status is saved |
108 | | // in status_. Not directly returning Status to save copying status |
109 | | // object to map previous performance of mmap mode. |
110 | | inline bool ReadVarint32(uint32_t offset, uint32_t* output, |
111 | | uint32_t* bytes_read); |
112 | | |
113 | | bool ReadVarint32NonMmap(uint32_t offset, uint32_t* output, |
114 | | uint32_t* bytes_read); |
115 | | |
116 | 0 | Status status() const { return status_; } |
117 | | |
118 | 0 | const PlainTableReaderFileInfo* file_info() { return file_info_; } |
119 | | |
120 | | private: |
121 | | const PlainTableReaderFileInfo* file_info_; |
122 | | |
123 | | struct Buffer { |
124 | 0 | Buffer() : buf_start_offset(0), buf_len(0), buf_capacity(0) {} |
125 | | std::unique_ptr<char[]> buf; |
126 | | uint32_t buf_start_offset; |
127 | | uint32_t buf_len; |
128 | | uint32_t buf_capacity; |
129 | | }; |
130 | | |
131 | | // Keep buffers for two recent reads. |
132 | | std::array<std::unique_ptr<Buffer>, 2> buffers_; |
133 | | uint32_t num_buf_; |
134 | | Status status_; |
135 | | |
136 | | Slice GetFromBuffer(Buffer* buf, uint32_t file_offset, uint32_t len); |
137 | | }; |
138 | | |
139 | | // A helper class to decode keys from input buffer |
140 | | // The class is used by PlainTableBuilder. |
141 | | class PlainTableKeyDecoder { |
142 | | public: |
143 | | explicit PlainTableKeyDecoder(const PlainTableReaderFileInfo* file_info, |
144 | | EncodingType encoding_type, |
145 | | uint32_t user_key_len, |
146 | | const SliceTransform* prefix_extractor) |
147 | 0 | : file_reader_(file_info), |
148 | 0 | encoding_type_(encoding_type), |
149 | 0 | prefix_len_(0), |
150 | 0 | fixed_user_key_len_(user_key_len), |
151 | 0 | prefix_extractor_(prefix_extractor), |
152 | 0 | in_prefix_(false) {} |
153 | | |
154 | | // Find the next key. |
155 | | // start: char array where the key starts. |
156 | | // limit: boundary of the char array |
157 | | // parsed_key: the output of the result key |
158 | | // internal_key: if not null, fill with the output of the result key in |
159 | | // un-parsed format |
160 | | // bytes_read: how many bytes read from start. Output |
161 | | // seekable: whether key can be read from this place. Used when building |
162 | | // indexes. Output. |
163 | | Status NextKey(uint32_t start_offset, ParsedInternalKey* parsed_key, |
164 | | Slice* internal_key, Slice* value, uint32_t* bytes_read, |
165 | | bool* seekable = nullptr); |
166 | | |
167 | | Status NextKeyNoValue(uint32_t start_offset, ParsedInternalKey* parsed_key, |
168 | | Slice* internal_key, uint32_t* bytes_read, |
169 | | bool* seekable = nullptr); |
170 | | |
171 | | PlainTableFileReader file_reader_; |
172 | | EncodingType encoding_type_; |
173 | | uint32_t prefix_len_; |
174 | | uint32_t fixed_user_key_len_; |
175 | | Slice saved_user_key_; |
176 | | IterKey cur_key_; |
177 | | const SliceTransform* prefix_extractor_; |
178 | | bool in_prefix_; |
179 | | |
180 | | private: |
181 | | Status NextPlainEncodingKey(uint32_t start_offset, |
182 | | ParsedInternalKey* parsed_key, |
183 | | Slice* internal_key, uint32_t* bytes_read, |
184 | | bool* seekable = nullptr); |
185 | | Status NextPrefixEncodingKey(uint32_t start_offset, |
186 | | ParsedInternalKey* parsed_key, |
187 | | Slice* internal_key, uint32_t* bytes_read, |
188 | | bool* seekable = nullptr); |
189 | | Status ReadInternalKey(uint32_t file_offset, uint32_t user_key_size, |
190 | | ParsedInternalKey* parsed_key, uint32_t* bytes_read, |
191 | | bool* internal_key_valid, Slice* internal_key); |
192 | | inline Status DecodeSize(uint32_t start_offset, |
193 | | PlainTableEntryType* entry_type, uint32_t* key_size, |
194 | | uint32_t* bytes_read); |
195 | | }; |
196 | | |
197 | | } // namespace ROCKSDB_NAMESPACE |