summaryrefslogtreecommitdiffstats
path: root/storage/rocksdb/rdb_converter.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/rocksdb/rdb_converter.h')
-rw-r--r--storage/rocksdb/rdb_converter.h247
1 files changed, 247 insertions, 0 deletions
diff --git a/storage/rocksdb/rdb_converter.h b/storage/rocksdb/rdb_converter.h
new file mode 100644
index 00000000..6ace89b3
--- /dev/null
+++ b/storage/rocksdb/rdb_converter.h
@@ -0,0 +1,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