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
|