1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
/*
Copyright (c) 2018, Facebook, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
#pragma once
// C++ standard header files
#include <string>
#include <vector>
// MySQL header files
#include "./handler.h" // handler
#include "./my_global.h" // ulonglong
#include "./sql_string.h"
#include "./ut0counter.h"
// MyRocks header files
#include "./ha_rocksdb.h"
#include "./rdb_datadic.h"
namespace myrocks {
class Rdb_field_encoder;
/**
Describes instructions on how to decode the field for value slice
*/
struct READ_FIELD {
// Points to Rdb_field_encoder describing the field
Rdb_field_encoder *m_field_enc;
// if true, decode the field, otherwise skip it
bool m_decode;
// Skip this many bytes before reading (or skipping) this field
int m_skip;
};
/**
Class to convert rocksdb value slice from storage format to mysql record
format.
*/
class Rdb_convert_to_record_value_decoder {
public:
Rdb_convert_to_record_value_decoder() = delete;
Rdb_convert_to_record_value_decoder(
const Rdb_convert_to_record_value_decoder &decoder) = delete;
Rdb_convert_to_record_value_decoder &operator=(
const Rdb_convert_to_record_value_decoder &decoder) = delete;
static int decode(uchar *const buf, uint *offset, TABLE *table,
my_core::Field *field, Rdb_field_encoder *field_dec,
Rdb_string_reader *reader, bool decode, bool is_null);
private:
static int decode_blob(TABLE *table, Field *field, Rdb_string_reader *reader,
bool decode);
static int decode_fixed_length_field(Field *const field,
Rdb_field_encoder *field_dec,
Rdb_string_reader *const reader,
bool decode);
static int decode_varchar(Field *const field, Rdb_string_reader *const reader,
bool decode);
};
/**
Class to iterator fields in RocksDB value slice
A template class instantiation represent a way to decode the data.
The reason to use template class instead of normal class is to elimate
virtual method call.
*/
template <typename value_field_decoder>
class Rdb_value_field_iterator {
private:
bool m_is_null;
std::vector<READ_FIELD>::const_iterator m_field_iter;
std::vector<READ_FIELD>::const_iterator m_field_end;
Rdb_string_reader *m_value_slice_reader;
// null value map
const char *m_null_bytes;
// The current open table
TABLE *m_table;
// The current field
Field *m_field;
Rdb_field_encoder *m_field_dec;
uchar *const m_buf;
uint m_offset;
public:
Rdb_value_field_iterator(TABLE *table, Rdb_string_reader *value_slice_reader,
const Rdb_converter *rdb_converter,
uchar *const buf);
Rdb_value_field_iterator(const Rdb_value_field_iterator &field_iterator) =
delete;
Rdb_value_field_iterator &operator=(
const Rdb_value_field_iterator &field_iterator) = delete;
/*
Move and decode next field
Run next() before accessing data
*/
int next();
// Whether current field is the end of fields
bool end_of_fields() const;
void *get_dst() const;
// Whether the value of current field is null
bool is_null() const;
// get current field index
int get_field_index() const;
// get current field type
enum_field_types get_field_type() const;
// get current field
Field *get_field() const;
};
/**
Class to convert Mysql formats to rocksdb storage format, and vice versa.
*/
class Rdb_converter {
public:
/*
Initialize converter with table data
*/
Rdb_converter(const THD *thd, const Rdb_tbl_def *tbl_def, TABLE *table);
Rdb_converter(const Rdb_converter &decoder) = delete;
Rdb_converter &operator=(const Rdb_converter &decoder) = delete;
~Rdb_converter();
void setup_field_decoders(const MY_BITMAP *field_map,
bool decode_all_fields = false);
int decode(const std::shared_ptr<Rdb_key_def> &key_def, uchar *dst,
const rocksdb::Slice *key_slice,
const rocksdb::Slice *value_slice);
int encode_value_slice(const std::shared_ptr<Rdb_key_def> &pk_def,
const rocksdb::Slice &pk_packed_slice,
Rdb_string_writer *pk_unpack_info, bool is_update_row,
bool store_row_debug_checksums, char *ttl_bytes,
bool *is_ttl_bytes_updated,
rocksdb::Slice *const value_slice);
my_core::ha_rows get_row_checksums_checked() const {
return m_row_checksums_checked;
}
bool get_verify_row_debug_checksums() const {
return m_verify_row_debug_checksums;
}
void set_verify_row_debug_checksums(bool verify_row_debug_checksums) {
m_verify_row_debug_checksums = verify_row_debug_checksums;
}
const Rdb_field_encoder *get_encoder_arr() const { return m_encoder_arr; }
int get_null_bytes_in_record() { return m_null_bytes_length_in_record; }
const char *get_null_bytes() const { return m_null_bytes; }
void set_is_key_requested(bool key_requested) {
m_key_requested = key_requested;
}
bool get_maybe_unpack_info() const { return m_maybe_unpack_info; }
char *get_ttl_bytes_buffer() { return m_ttl_bytes; }
const std::vector<READ_FIELD> *get_decode_fields() const {
return &m_decoders_vect;
}
private:
int decode_value_header(Rdb_string_reader *reader,
const std::shared_ptr<Rdb_key_def> &pk_def,
rocksdb::Slice *unpack_slice);
void setup_field_encoders();
void get_storage_type(Rdb_field_encoder *const encoder, const uint kp);
int convert_record_from_storage_format(
const std::shared_ptr<Rdb_key_def> &pk_def,
const rocksdb::Slice *const key, const rocksdb::Slice *const value,
uchar *const buf);
int verify_row_debug_checksum(const std::shared_ptr<Rdb_key_def> &pk_def,
Rdb_string_reader *reader,
const rocksdb::Slice *key,
const rocksdb::Slice *value);
private:
/*
This tells if any field which is part of the key needs to be unpacked and
decoded.
*/
bool m_key_requested;
/*
Controls whether verifying checksums during reading, This is updated from
the session variable at the start of each query.
*/
bool m_verify_row_debug_checksums;
// Thread handle
const THD *m_thd;
/* MyRocks table definition*/
const Rdb_tbl_def *m_tbl_def;
/* The current open table */
TABLE *m_table;
/*
Number of bytes in on-disk (storage) record format that are used for
storing SQL NULL flags.
*/
int m_null_bytes_length_in_record;
/*
Pointer to null bytes value
*/
const char *m_null_bytes;
/*
TRUE <=> Some fields in the PK may require unpack_info.
*/
bool m_maybe_unpack_info;
/*
Pointer to the original TTL timestamp value (8 bytes) during UPDATE.
*/
char m_ttl_bytes[ROCKSDB_SIZEOF_TTL_RECORD];
/*
Array of table->s->fields elements telling how to store fields in the
record.
*/
Rdb_field_encoder *m_encoder_arr;
/*
Array of request fields telling how to decode data in RocksDB format
*/
std::vector<READ_FIELD> m_decoders_vect;
/*
A counter of how many row checksums were checked for this table. Note that
this does not include checksums for secondary index entries.
*/
my_core::ha_rows m_row_checksums_checked;
// buffer to hold data during encode_value_slice
String m_storage_record;
};
} // namespace myrocks
|