1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00
commit d1bb19b8f751875472211312c8e810143a7ba4b6
Author: Manuel Ung <mung@fb.com>
Date:   Fri Feb 3 11:50:34 2017 -0800

    Add cardinality stats to information schema

    Summary: This adds cardinality stats to the INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP table. This is the only missing user collected properties from SST files that we don't expose, which is useful for debugging cardinality bugs.

    Reviewed By: hermanlee

    Differential Revision: D4509156

    fbshipit-source-id: 2d3918a
This commit is contained in:
Sergei Petrunia
2017-02-06 17:39:08 +00:00
parent cfb59f3196
commit 7468ccfadf
82 changed files with 9204 additions and 10486 deletions

View File

@@ -22,8 +22,8 @@
#include <vector>
/* MySQL includes */
#include <mysql/plugin.h>
#include <my_global.h>
#include <mysql/plugin.h>
/* MyRocks includes */
#include "./ha_rocksdb.h"
@@ -33,10 +33,8 @@
namespace myrocks {
static std::vector<Rdb_index_stats>
extract_index_stats(
const std::vector<std::string>& files,
const rocksdb::TablePropertiesCollection& props
) {
extract_index_stats(const std::vector<std::string> &files,
const rocksdb::TablePropertiesCollection &props) {
std::vector<Rdb_index_stats> ret;
for (auto fn : files) {
const auto it = props.find(fn);
@@ -49,8 +47,7 @@ extract_index_stats(
}
void Rdb_event_listener::update_index_stats(
const rocksdb::TableProperties& props
) {
const rocksdb::TableProperties &props) {
DBUG_ASSERT(m_ddl_manager != nullptr);
const auto tbl_props =
std::make_shared<const rocksdb::TableProperties>(props);
@@ -62,9 +59,7 @@ void Rdb_event_listener::update_index_stats(
}
void Rdb_event_listener::OnCompactionCompleted(
rocksdb::DB *db,
const rocksdb::CompactionJobInfo& ci
) {
rocksdb::DB *db, const rocksdb::CompactionJobInfo &ci) {
DBUG_ASSERT(db != nullptr);
DBUG_ASSERT(m_ddl_manager != nullptr);
@@ -76,17 +71,13 @@ void Rdb_event_listener::OnCompactionCompleted(
}
void Rdb_event_listener::OnFlushCompleted(
rocksdb::DB* db,
const rocksdb::FlushJobInfo& flush_job_info
) {
rocksdb::DB *db, const rocksdb::FlushJobInfo &flush_job_info) {
DBUG_ASSERT(db != nullptr);
update_index_stats(flush_job_info.table_properties);
}
void Rdb_event_listener::OnExternalFileIngested(
rocksdb::DB* db,
const rocksdb::ExternalFileIngestionInfo& info
) {
rocksdb::DB *db, const rocksdb::ExternalFileIngestionInfo &info) {
DBUG_ASSERT(db != nullptr);
update_index_stats(info.table_properties);
}

View File

@@ -21,29 +21,26 @@ namespace myrocks {
class Rdb_ddl_manager;
class Rdb_event_listener : public rocksdb::EventListener
{
class Rdb_event_listener : public rocksdb::EventListener {
public:
Rdb_event_listener(const Rdb_event_listener &) = delete;
Rdb_event_listener &operator=(const Rdb_event_listener &) = delete;
explicit Rdb_event_listener(Rdb_ddl_manager* const ddl_manager) :
m_ddl_manager(ddl_manager) {
}
explicit Rdb_event_listener(Rdb_ddl_manager *const ddl_manager)
: m_ddl_manager(ddl_manager) {}
void OnCompactionCompleted(
rocksdb::DB* db, const rocksdb::CompactionJobInfo& ci) override;
void OnFlushCompleted(
rocksdb::DB* db, const rocksdb::FlushJobInfo& flush_job_info) override;
void OnCompactionCompleted(rocksdb::DB *db,
const rocksdb::CompactionJobInfo &ci) override;
void OnFlushCompleted(rocksdb::DB *db,
const rocksdb::FlushJobInfo &flush_job_info) override;
void OnExternalFileIngested(
rocksdb::DB* db, const rocksdb::ExternalFileIngestionInfo& ingestion_info)
override;
rocksdb::DB *db,
const rocksdb::ExternalFileIngestionInfo &ingestion_info) override;
private:
Rdb_ddl_manager *m_ddl_manager;
void update_index_stats(
const rocksdb::TableProperties& props);
void update_index_stats(const rocksdb::TableProperties &props);
};
} // namespace myrocks

File diff suppressed because it is too large Load Diff

View File

@@ -111,6 +111,16 @@ const char * const HIDDEN_PK_NAME= "HIDDEN_PK_ID";
*/
const char *const PER_INDEX_CF_NAME = "$per_index_cf";
/*
Name for the background thread.
*/
const char *const BG_THREAD_NAME = "myrocks-bg";
/*
Name for the drop index thread.
*/
const char *const INDEX_THREAD_NAME = "myrocks-index";
/*
Default, minimal valid, and maximum valid sampling rate values when collecting
statistics about table.
@@ -184,8 +194,7 @@ const char * const PER_INDEX_CF_NAME = "$per_index_cf";
#define HA_ERR_ROCKSDB_TOO_MANY_LOCKS (HA_ERR_LAST + 3)
#define HA_ERR_ROCKSDB_LAST HA_ERR_ROCKSDB_TOO_MANY_LOCKS
inline bool looks_like_per_index_cf_typo(const char* const name)
{
inline bool looks_like_per_index_cf_typo(const char *const name) {
return (name && name[0] == '$' && strcmp(name, PER_INDEX_CF_NAME));
}
@@ -196,8 +205,7 @@ inline bool looks_like_per_index_cf_typo(const char* const name)
//TODO: join this with Rdb_tbl_def ?
*/
struct Rdb_table_handler
{
struct Rdb_table_handler {
char *m_table_name;
uint m_table_name_length;
int m_ref_count;
@@ -209,8 +217,6 @@ struct Rdb_table_handler
Rdb_atomic_perf_counters m_table_perf_context;
};
class Rdb_key_def;
class Rdb_tbl_def;
class Rdb_transaction;
@@ -223,31 +229,25 @@ const char *const rocksdb_hton_name= "ROCKSDB";
typedef struct _gl_index_id_s {
uint32_t cf_id;
uint32_t index_id;
bool operator==(const struct _gl_index_id_s& other) const
{
bool operator==(const struct _gl_index_id_s &other) const {
return cf_id == other.cf_id && index_id == other.index_id;
}
bool operator!=(const struct _gl_index_id_s& other) const
{
bool operator!=(const struct _gl_index_id_s &other) const {
return cf_id != other.cf_id || index_id != other.index_id;
}
bool operator<(const struct _gl_index_id_s& other) const
{
bool operator<(const struct _gl_index_id_s &other) const {
return cf_id < other.cf_id ||
(cf_id == other.cf_id && index_id < other.index_id);
}
bool operator<=(const struct _gl_index_id_s& other) const
{
bool operator<=(const struct _gl_index_id_s &other) const {
return cf_id < other.cf_id ||
(cf_id == other.cf_id && index_id <= other.index_id);
}
bool operator>(const struct _gl_index_id_s& other) const
{
bool operator>(const struct _gl_index_id_s &other) const {
return cf_id > other.cf_id ||
(cf_id == other.cf_id && index_id > other.index_id);
}
bool operator>=(const struct _gl_index_id_s& other) const
{
bool operator>=(const struct _gl_index_id_s &other) const {
return cf_id > other.cf_id ||
(cf_id == other.cf_id && index_id >= other.index_id);
}
@@ -295,13 +295,10 @@ struct st_export_stats {
/* Provide hash function for GL_INDEX_ID so we can include it in sets */
namespace std {
template <>
struct hash<myrocks::GL_INDEX_ID>
{
std::size_t operator()(const myrocks::GL_INDEX_ID& gl_index_id) const
{
const uint64_t val = ((uint64_t) gl_index_id.cf_id << 32 |
(uint64_t) gl_index_id.index_id);
template <> struct hash<myrocks::GL_INDEX_ID> {
std::size_t operator()(const myrocks::GL_INDEX_ID &gl_index_id) const {
const uint64_t val =
((uint64_t)gl_index_id.cf_id << 32 | (uint64_t)gl_index_id.index_id);
return std::hash<uint64_t>()(val);
}
};
@@ -314,8 +311,7 @@ namespace myrocks {
Class definition for ROCKSDB storage engine plugin handler
*/
class ha_rocksdb: public my_core::handler
{
class ha_rocksdb : public my_core::handler {
my_core::THR_LOCK_DATA m_db_lock; ///< MySQL database lock
Rdb_table_handler *m_table_handler; ///< Open table handler
@@ -387,6 +383,10 @@ class ha_rocksdb: public my_core::handler
uchar *m_sk_packed_tuple_old;
Rdb_string_writer m_sk_tails_old;
/* Buffers used for duplicate checking during unique_index_creation */
uchar *m_dup_sk_packed_tuple;
uchar *m_dup_sk_packed_tuple_old;
/*
Temporary space for packing VARCHARs (we provide it to
pack_record()/pack_index_tuple() calls).
@@ -452,36 +452,33 @@ class ha_rocksdb: public my_core::handler
Rdb_tbl_def *const tbl_def_arg,
const TABLE *const old_table_arg = nullptr,
const Rdb_tbl_def *const old_tbl_def_arg = nullptr) const
__attribute__((__nonnull__(2, 3), __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__(2, 3), __warn_unused_result__));
int secondary_index_read(const int keyno, uchar *const buf)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void setup_iterator_for_rnd_scan();
void setup_scan_iterator(const Rdb_key_def &kd, rocksdb::Slice *const slice)
__attribute__((__nonnull__))
{
MY_ATTRIBUTE((__nonnull__)) {
setup_scan_iterator(kd, slice, false, false, 0);
}
bool is_ascending(const Rdb_key_def &keydef,
enum ha_rkey_function find_flag) const
__attribute__((__nonnull__, __warn_unused_result__));
void setup_scan_iterator(const Rdb_key_def& kd,
rocksdb::Slice *slice, const bool use_all_keys,
const bool is_ascending, const uint eq_cond_len)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void setup_scan_iterator(const Rdb_key_def &kd, rocksdb::Slice *slice,
const bool use_all_keys, const bool is_ascending,
const uint eq_cond_len) MY_ATTRIBUTE((__nonnull__));
void release_scan_iterator(void);
rocksdb::Status get_for_update(Rdb_transaction* const tx,
rocksdb::Status
get_for_update(Rdb_transaction *const tx,
rocksdb::ColumnFamilyHandle *const column_family,
const rocksdb::Slice& key,
std::string* const value) const;
const rocksdb::Slice &key, std::string *const value) const;
int get_row_by_rowid(uchar *const buf, const char *const rowid,
const uint rowid_size)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int get_row_by_rowid(uchar *const buf, const uchar *const rowid,
const uint rowid_size)
__attribute__((__nonnull__, __warn_unused_result__))
{
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__)) {
return get_row_by_rowid(buf, reinterpret_cast<const char *>(rowid),
rowid_size);
}
@@ -489,18 +486,18 @@ class ha_rocksdb: public my_core::handler
void update_auto_incr_val();
void load_auto_incr_value();
longlong update_hidden_pk_val();
int load_hidden_pk_value() __attribute__((__warn_unused_result__));
int load_hidden_pk_value() MY_ATTRIBUTE((__warn_unused_result__));
int read_hidden_pk_id_from_rowkey(longlong *const hidden_pk_id)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
bool can_use_single_delete(const uint &index) const
__attribute__((__warn_unused_result__));
bool skip_unique_check() const __attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
bool skip_unique_check() const MY_ATTRIBUTE((__warn_unused_result__));
void set_force_skip_unique_check(bool skip) override;
bool commit_in_the_middle() __attribute__((__warn_unused_result__));
bool commit_in_the_middle() MY_ATTRIBUTE((__warn_unused_result__));
bool do_bulk_commit(Rdb_transaction *const tx)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
bool has_hidden_pk(const TABLE *const table) const
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void update_row_stats(const operation_type &type);
@@ -513,8 +510,7 @@ class ha_rocksdb: public my_core::handler
Rdb_field_encoder *m_encoder_arr;
/* Describes instructions on how to decode the field */
class READ_FIELD
{
class READ_FIELD {
public:
/* Points to Rdb_field_encoder describing the field */
Rdb_field_encoder *m_field_enc;
@@ -543,8 +539,9 @@ class ha_rocksdb: public my_core::handler
void get_storage_type(Rdb_field_encoder *const encoder, const uint &kp);
void setup_field_converters();
int alloc_key_buffers(const TABLE *const table_arg,
const Rdb_tbl_def* const tbl_def_arg)
__attribute__((__nonnull__, __warn_unused_result__));
const Rdb_tbl_def *const tbl_def_arg,
bool alloc_alter_buffers = false)
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void free_key_buffers();
// the buffer size should be at least 2*Rdb_key_def::INDEX_NUMBER_SIZE
@@ -568,7 +565,8 @@ class ha_rocksdb: public my_core::handler
public:
/*
Controls whether writes include checksums. This is updated from the session variable
Controls whether writes include checksums. This is updated from the session
variable
at the start of each query.
*/
bool m_store_row_debug_checksums;
@@ -579,9 +577,8 @@ public:
ha_rocksdb(my_core::handlerton *const hton,
my_core::TABLE_SHARE *const table_arg);
~ha_rocksdb()
{
int err __attribute__((__unused__));
~ha_rocksdb() {
int err MY_ATTRIBUTE((__unused__));
err = finalize_bulk_load();
DBUG_ASSERT(err == 0);
mysql_mutex_destroy(&m_bulk_load_mutex);
@@ -590,15 +587,23 @@ public:
/** @brief
The name that will be used for display purposes.
*/
const char *table_type() const { return rocksdb_hton_name; }
const char *table_type() const override {
DBUG_ENTER_FUNC();
DBUG_RETURN(rocksdb_hton_name);
}
/* The following is only used by SHOW KEYS: */
const char *index_type(uint inx) { return "LSMTREE"; }
const char *index_type(uint inx) override {
DBUG_ENTER_FUNC();
DBUG_RETURN("LSMTREE");
}
/** @brief
The file extensions.
*/
const char **bas_ext() const;
const char **bas_ext() const override;
/*
See if this is the same base table - this should only be true for different
@@ -610,8 +615,9 @@ public:
This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h
*/
ulonglong table_flags() const override
{
ulonglong table_flags() const override {
DBUG_ENTER_FUNC();
/*
HA_BINLOG_STMT_CAPABLE
We are saying that this engine is just statement capable to have
@@ -621,12 +627,11 @@ public:
If we don't set it, filesort crashes, because it assumes rowids are
1..8 byte numbers
*/
return HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
DBUG_RETURN(HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_REC_NOT_IN_SEQ | HA_CAN_INDEX_BLOBS |
(m_pk_can_be_decoded ? HA_PRIMARY_KEY_IN_READ_INDEX : 0) |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
HA_NULL_IN_KEY |
HA_PARTIAL_COLUMN_READ;
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_NULL_IN_KEY |
HA_PARTIAL_COLUMN_READ);
}
bool init_with_fields() override;
@@ -641,61 +646,62 @@ public:
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
ulong index_flags(uint inx, uint part, bool all_parts) const;
ulong index_flags(uint inx, uint part, bool all_parts) const override;
const key_map * keys_to_use_for_scanning()
{
return &key_map_full;
const key_map *keys_to_use_for_scanning() override {
DBUG_ENTER_FUNC();
DBUG_RETURN(&key_map_full);
}
bool primary_key_is_clustered()
{
return true;
bool primary_key_is_clustered() override {
DBUG_ENTER_FUNC();
DBUG_RETURN(true);
}
bool should_store_row_debug_checksums() const
{
bool should_store_row_debug_checksums() const {
return m_store_row_debug_checksums && (rand() % 100 < m_checksums_pct);
}
int rename_table(const char* const from, const char* const to)
__attribute__((__nonnull__, __warn_unused_result__));
int rename_table(const char *const from, const char *const to) override
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int convert_record_from_storage_format(const rocksdb::Slice *const key,
const rocksdb::Slice *const value,
uchar *const buf)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int convert_record_from_storage_format(const rocksdb::Slice *const key,
uchar *const buf)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void convert_record_to_storage_format(const rocksdb::Slice &pk_packed_slice,
Rdb_string_writer *const pk_unpack_info,
rocksdb::Slice *const packed_rec)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
static const char *get_key_name(const uint index,
const TABLE *const table_arg,
const Rdb_tbl_def *const tbl_def_arg)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
static const char *get_key_comment(const uint index,
const TABLE *const table_arg,
const Rdb_tbl_def *const tbl_def_arg)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
static bool is_hidden_pk(const uint index, const TABLE *const table_arg,
const Rdb_tbl_def *const tbl_def_arg)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
static uint pk_index(const TABLE *const table_arg,
const Rdb_tbl_def *const tbl_def_arg)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
static bool is_pk(const uint index, const TABLE *table_arg,
const Rdb_tbl_def *tbl_def_arg)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
@@ -704,11 +710,30 @@ public:
send. Return *real* limits of your storage engine here; MySQL will do
min(your_limits, MySQL_limits) automatically.
*/
uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_supported_record_length() const override {
DBUG_ENTER_FUNC();
DBUG_RETURN(HA_MAX_REC_LENGTH);
}
uint max_supported_keys() const override {
DBUG_ENTER_FUNC();
DBUG_RETURN(MAX_INDEXES);
}
uint max_supported_key_parts() const override {
DBUG_ENTER_FUNC();
DBUG_RETURN(MAX_REF_PARTS);
}
uint max_supported_key_part_length() const override {
DBUG_ENTER_FUNC();
DBUG_RETURN(2048);
}
uint max_supported_keys() const { return MAX_INDEXES; }
uint max_supported_key_parts() const { return MAX_REF_PARTS; }
uint max_supported_key_part_length() const { return 2048; }
/** @brief
unireg.cc will call this to make sure that the storage engine can handle
the data it is about to send. Return *real* limits of your storage engine
@@ -718,76 +743,93 @@ public:
There is no need to implement ..._key_... methods if your engine doesn't
support indexes.
*/
uint max_supported_key_length() const { return 16*1024; /* just to return something*/ }
uint max_supported_key_length() const override {
DBUG_ENTER_FUNC();
DBUG_RETURN(16 * 1024); /* just to return something*/
}
/**
TODO: return actual upper bound of number of records in the table.
(e.g. save number of records seen on full table scan and/or use file size
as upper bound)
*/
ha_rows estimate_rows_upper_bound() { return HA_POS_ERROR; }
ha_rows estimate_rows_upper_bound() override {
DBUG_ENTER_FUNC();
/* At the moment, we're ok with default handler::index_init() implementation. */
DBUG_RETURN(HA_POS_ERROR);
}
/* At the moment, we're ok with default handler::index_init() implementation.
*/
int index_read_map(uchar *const buf, const uchar *const key,
key_part_map keypart_map,
enum ha_rkey_function find_flag);
__attribute__((__warn_unused_result__));
enum ha_rkey_function find_flag) override
MY_ATTRIBUTE((__warn_unused_result__));
int index_read_map_impl(uchar *const buf, const uchar *const key,
key_part_map keypart_map,
enum ha_rkey_function find_flag,
const key_range *end_key)
__attribute__((__warn_unused_result__));;
MY_ATTRIBUTE((__warn_unused_result__));
int index_read_last_map(uchar *const buf, const uchar *const key,
key_part_map keypart_map)
__attribute__((__warn_unused_result__));;
key_part_map keypart_map) override
MY_ATTRIBUTE((__warn_unused_result__));
int read_range_first(const key_range *const start_key,
const key_range* const end_key,
bool eq_range, bool sorted)
__attribute__((__warn_unused_result__));;
const key_range *const end_key, bool eq_range,
bool sorted) override
MY_ATTRIBUTE((__warn_unused_result__));
virtual double scan_time() override {
DBUG_ENTER_FUNC();
DBUG_RETURN(
static_cast<double>((stats.records + stats.deleted) / 20.0 + 10));
}
virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
virtual double read_time(uint, uint, ha_rows rows) override;
int open(const char* const name, int mode, uint test_if_locked)
__attribute__((__warn_unused_result__));
int close(void) __attribute__((__warn_unused_result__));
int open(const char *const name, int mode, uint test_if_locked) override
MY_ATTRIBUTE((__warn_unused_result__));
int close(void) override MY_ATTRIBUTE((__warn_unused_result__));
int write_row(uchar* const buf) __attribute__((__warn_unused_result__));
int update_row(const uchar* const old_data, uchar* const new_data)
__attribute__((__warn_unused_result__));
int delete_row(const uchar* const buf)
__attribute__((__warn_unused_result__));
rocksdb::Status delete_or_singledelete(uint index,
Rdb_transaction* const tx,
int write_row(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
int update_row(const uchar *const old_data, uchar *const new_data) override
MY_ATTRIBUTE((__warn_unused_result__));
int delete_row(const uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
rocksdb::Status delete_or_singledelete(uint index, Rdb_transaction *const tx,
rocksdb::ColumnFamilyHandle *const cf,
const rocksdb::Slice &key)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int index_next(uchar* const buf) __attribute__((__warn_unused_result__));
int index_next(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
int index_next_with_direction(uchar *const buf, bool move_forward)
__attribute__((__warn_unused_result__));
int index_prev(uchar* const buf) __attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int index_prev(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
int index_first(uchar* const buf) __attribute__((__warn_unused_result__));
int index_last(uchar* const buf) __attribute__((__warn_unused_result__));
int index_first(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
int index_last(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
class Item* idx_cond_push(uint keyno, class Item* const idx_cond);
class Item *idx_cond_push(uint keyno, class Item *const idx_cond) override;
/*
Default implementation from cancel_pushed_idx_cond() suits us
*/
private:
struct key_def_cf_info
{
struct key_def_cf_info {
rocksdb::ColumnFamilyHandle *cf_handle;
bool is_reverse_cf;
bool is_auto_cf;
};
struct update_row_info
{
struct update_row_info {
Rdb_transaction *tx;
const uchar *new_data;
const uchar *old_data;
@@ -801,112 +843,124 @@ private:
bool skip_unique_check;
};
/*
Used to check for duplicate entries during fast unique secondary index
creation.
*/
struct unique_sk_buf_info {
bool sk_buf_switch = false;
rocksdb::Slice sk_memcmp_key;
rocksdb::Slice sk_memcmp_key_old;
uchar *dup_sk_buf;
uchar *dup_sk_buf_old;
/*
This method is meant to be called back to back during inplace creation
of unique indexes. It will switch between two buffers, which
will each store the memcmp form of secondary keys, which are then
converted to slices in sk_memcmp_key or sk_memcmp_key_old.
Switching buffers on each iteration allows us to retain the
sk_memcmp_key_old value for duplicate comparison.
*/
inline uchar *swap_and_get_sk_buf() {
sk_buf_switch = !sk_buf_switch;
return sk_buf_switch ? dup_sk_buf : dup_sk_buf_old;
}
};
int create_cfs(const TABLE *const table_arg, Rdb_tbl_def *const tbl_def_arg,
std::array<struct key_def_cf_info, MAX_INDEXES + 1>* const cfs) const;
__attribute__((__nonnull__, __warn_unused_result__));
std::array<struct key_def_cf_info, MAX_INDEXES + 1> *const cfs)
const MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int create_key_def(const TABLE *const table_arg, const uint &i,
const Rdb_tbl_def *const tbl_def_arg,
std::shared_ptr<Rdb_key_def> *const new_key_def,
const struct key_def_cf_info& cf_info) const;
__attribute__((__nonnull__, __warn_unused_result__));
const struct key_def_cf_info &cf_info) const
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int create_inplace_key_defs(const TABLE* const table_arg,
Rdb_tbl_def* vtbl_def_arg,
int create_inplace_key_defs(
const TABLE *const table_arg, Rdb_tbl_def *vtbl_def_arg,
const TABLE *const old_table_arg,
const Rdb_tbl_def *const old_tbl_def_arg,
const std::array<key_def_cf_info, MAX_INDEXES + 1>& cfs) const;
__attribute__((__nonnull__, __warn_unused_result__));
const std::array<key_def_cf_info, MAX_INDEXES + 1> &cfs) const
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
std::unordered_map<std::string, uint> get_old_key_positions(
const TABLE* table_arg,
const Rdb_tbl_def* tbl_def_arg,
std::unordered_map<std::string, uint>
get_old_key_positions(const TABLE *table_arg, const Rdb_tbl_def *tbl_def_arg,
const TABLE *old_table_arg,
const Rdb_tbl_def *old_tbl_def_arg) const
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
int compare_key_parts(const KEY *const old_key,
const KEY *const new_key) const;
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int index_first_intern(uchar *buf)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int index_last_intern(uchar *buf)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
enum icp_result check_index_cond() const;
int find_icp_matching_index_rec(const bool &move_forward, uchar *const buf)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void calc_updated_indexes();
int update_write_row(const uchar *const old_data, const uchar *const new_data,
const bool skip_unique_check)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int get_pk_for_update(struct update_row_info *const row_info);
int check_and_lock_unique_pk(const uint &key_id,
const struct update_row_info &row_info,
bool *const found, bool *const pk_changed)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int check_and_lock_sk(const uint &key_id,
const struct update_row_info &row_info,
bool *const found) const
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int check_uniqueness_and_lock(const struct update_row_info &row_info,
bool *const pk_changed)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
bool over_bulk_load_threshold(int *err)
__attribute__((__warn_unused_result__));
int bulk_load_key(Rdb_transaction* const tx,
const Rdb_key_def& kd,
const rocksdb::Slice& key,
const rocksdb::Slice& value)
__attribute__((__nonnull__, __warn_unused_result__));
int update_pk(const Rdb_key_def& kd,
const struct update_row_info& row_info,
const bool &pk_changed)
__attribute__((__warn_unused_result__));
int update_sk(const TABLE* const table_arg,
const Rdb_key_def& kd,
MY_ATTRIBUTE((__warn_unused_result__));
int check_duplicate_sk(const TABLE *table_arg, const Rdb_key_def &index,
const rocksdb::Slice *key,
struct unique_sk_buf_info *sk_info)
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int bulk_load_key(Rdb_transaction *const tx, const Rdb_key_def &kd,
const rocksdb::Slice &key, const rocksdb::Slice &value)
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int update_pk(const Rdb_key_def &kd, const struct update_row_info &row_info,
const bool &pk_changed) MY_ATTRIBUTE((__warn_unused_result__));
int update_sk(const TABLE *const table_arg, const Rdb_key_def &kd,
const struct update_row_info &row_info)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int update_indexes(const struct update_row_info &row_info,
const bool &pk_changed)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int read_key_exact(const Rdb_key_def& kd,
rocksdb::Iterator* const iter, const bool &using_full_key,
int read_key_exact(const Rdb_key_def &kd, rocksdb::Iterator *const iter,
const bool &using_full_key,
const rocksdb::Slice &key_slice) const
__attribute__((__nonnull__, __warn_unused_result__));
int read_before_key(const Rdb_key_def& kd,
const bool &using_full_key,
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int read_before_key(const Rdb_key_def &kd, const bool &using_full_key,
const rocksdb::Slice &key_slice)
__attribute__((__nonnull__, __warn_unused_result__));
int read_after_key(const Rdb_key_def& kd,
const bool &using_full_key,
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int read_after_key(const Rdb_key_def &kd, const bool &using_full_key,
const rocksdb::Slice &key_slice)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int position_to_correct_key(const Rdb_key_def& kd,
const enum ha_rkey_function &find_flag,
const bool &full_key_match,
const uchar* const key,
const key_part_map &keypart_map,
const rocksdb::Slice& key_slice,
bool* const move_forward)
__attribute__((__warn_unused_result__));
int position_to_correct_key(
const Rdb_key_def &kd, const enum ha_rkey_function &find_flag,
const bool &full_key_match, const uchar *const key,
const key_part_map &keypart_map, const rocksdb::Slice &key_slice,
bool *const move_forward) MY_ATTRIBUTE((__warn_unused_result__));
int read_row_from_primary_key(uchar *const buf)
__attribute__((__nonnull__, __warn_unused_result__));
int read_row_from_secondary_key(uchar* const buf,
const Rdb_key_def& kd,
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int read_row_from_secondary_key(uchar *const buf, const Rdb_key_def &kd,
bool move_forward)
__attribute__((__nonnull__, __warn_unused_result__));
int try_keyonly_read_from_sk(uchar* buf,
const Rdb_key_def& kd,
const rocksdb::Slice& key,
const rocksdb::Slice& value,
uint rowid_size)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int calc_eq_cond_len(const Rdb_key_def &kd,
const enum ha_rkey_function &find_flag,
@@ -914,26 +968,28 @@ private:
const int &bytes_changed_by_succ,
const key_range *const end_key,
uint *const end_key_packed_size)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
Rdb_tbl_def *get_table_if_exists(const char *const tablename)
__attribute__((__nonnull__, __warn_unused_result__));
void read_thd_vars(THD* const thd)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void read_thd_vars(THD *const thd) MY_ATTRIBUTE((__nonnull__));
const char *thd_rocksdb_tmpdir()
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
bool contains_foreign_key(THD *const thd)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int inplace_populate_sk(const TABLE* const table_arg,
const std::unordered_set<std::shared_ptr<Rdb_key_def>>& indexes);
int inplace_populate_sk(
TABLE *const table_arg,
const std::unordered_set<std::shared_ptr<Rdb_key_def>> &indexes)
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
public:
int index_init(uint idx, bool sorted) __attribute__((__warn_unused_result__));
int index_end() __attribute__((__warn_unused_result__));
int index_init(uint idx, bool sorted) override
MY_ATTRIBUTE((__warn_unused_result__));
int index_end() override MY_ATTRIBUTE((__warn_unused_result__));
void unlock_row();
void unlock_row() override;
/** @brief
Unlike index_init(), rnd_init() can be called two consecutive times
@@ -943,95 +999,102 @@ public:
cursor to the start of the table; no need to deallocate and allocate
it again. This is a required method.
*/
int rnd_init(bool scan) __attribute__((__warn_unused_result__));
int rnd_end() __attribute__((__warn_unused_result__));
int rnd_init(bool scan) override MY_ATTRIBUTE((__warn_unused_result__));
int rnd_end() override MY_ATTRIBUTE((__warn_unused_result__));
int rnd_next(uchar* const buf) __attribute__((__warn_unused_result__));
int rnd_next(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
int rnd_next_with_direction(uchar *const buf, bool move_forward)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
int rnd_pos(uchar* const buf, uchar* const pos)
__attribute__((__warn_unused_result__));
void position(const uchar* const record);
int rnd_pos(uchar *const buf, uchar *const pos) override
MY_ATTRIBUTE((__warn_unused_result__));
void position(const uchar *const record) override;
int info(uint) override;
/* This function will always return success, therefore no annotation related
* to checking the return value. Can't change the signature because it's
* required by the interface. */
int extra(enum ha_extra_function operation);
int extra(enum ha_extra_function operation) override;
int start_stmt(THD* const thd, thr_lock_type lock_type)
__attribute__((__warn_unused_result__));
int external_lock(THD* const thd, int lock_type)
__attribute__((__warn_unused_result__));
int delete_all_rows(ha_rows* const nrows) __attribute__((__warn_unused_result__));
int truncate() __attribute__((__warn_unused_result__));
int start_stmt(THD *const thd, thr_lock_type lock_type) override
MY_ATTRIBUTE((__warn_unused_result__));
int external_lock(THD *const thd, int lock_type) override
MY_ATTRIBUTE((__warn_unused_result__));
int truncate() override MY_ATTRIBUTE((__warn_unused_result__));
int reset() override {
DBUG_ENTER_FUNC();
int reset() override
{
/* Free blob data */
m_retrieved_record.clear();
return 0;
DBUG_RETURN(HA_EXIT_SUCCESS);
}
int check(THD* const thd, HA_CHECK_OPT* const check_opt)
__attribute__((__warn_unused_result__));
int check(THD *const thd, HA_CHECK_OPT *const check_opt) override
MY_ATTRIBUTE((__warn_unused_result__));
void remove_rows(Rdb_tbl_def *const tbl);
ha_rows records_in_range(uint inx, key_range *const min_key,
key_range* const max_key)
__attribute__((__warn_unused_result__));
int delete_table(const char* const from) __attribute__((__warn_unused_result__));
key_range *const max_key) override
MY_ATTRIBUTE((__warn_unused_result__));
int delete_table(const char *const from) override
MY_ATTRIBUTE((__warn_unused_result__));
int create(const char *const name, TABLE *const form,
HA_CREATE_INFO* const create_info)
__attribute__((__warn_unused_result__));
HA_CREATE_INFO *const create_info) override
MY_ATTRIBUTE((__warn_unused_result__));
bool check_if_incompatible_data(HA_CREATE_INFO *const info,
uint table_changes)
__attribute__((__warn_unused_result__));
uint table_changes) override
MY_ATTRIBUTE((__warn_unused_result__));
THR_LOCK_DATA **store_lock(THD *const thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
__attribute__((__warn_unused_result__));
enum thr_lock_type lock_type) override
MY_ATTRIBUTE((__warn_unused_result__));
my_bool register_query_cache_table(THD *const thd, char *const table_key,
uint key_length,
qc_engine_callback *const engine_callback,
ulonglong* const engine_data)
{
ulonglong *const engine_data) override {
DBUG_ENTER_FUNC();
/* Currently, we don't support query cache */
return FALSE;
DBUG_RETURN(FALSE);
}
bool get_error_message(const int error, String* const buf)
__attribute__((__nonnull__));
bool get_error_message(const int error, String *const buf) override
MY_ATTRIBUTE((__nonnull__));
void get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong nb_desired_values,
ulonglong *const first_value,
ulonglong* const nb_reserved_values);
void update_create_info(HA_CREATE_INFO* const create_info);
int optimize(THD* const thd, HA_CHECK_OPT* const check_opt)
__attribute__((__warn_unused_result__));
int analyze(THD* const thd, HA_CHECK_OPT* const check_opt)
__attribute__((__warn_unused_result__));
ulonglong *const nb_reserved_values) override;
void update_create_info(HA_CREATE_INFO *const create_info) override;
int optimize(THD *const thd, HA_CHECK_OPT *const check_opt) override
MY_ATTRIBUTE((__warn_unused_result__));
int analyze(THD *const thd, HA_CHECK_OPT *const check_opt) override
MY_ATTRIBUTE((__warn_unused_result__));
int calculate_stats(const TABLE *const table_arg, THD *const thd,
HA_CHECK_OPT *const check_opt)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
enum_alter_inplace_result check_if_supported_inplace_alter(
TABLE *altered_table,
my_core::Alter_inplace_info *const ha_alter_info) override;
bool prepare_inplace_alter_table(TABLE* const altered_table,
my_core::Alter_inplace_info* const ha_alter_info);
bool prepare_inplace_alter_table(
TABLE *const altered_table,
my_core::Alter_inplace_info *const ha_alter_info) override;
bool inplace_alter_table(TABLE* const altered_table,
my_core::Alter_inplace_info* const ha_alter_info);
bool inplace_alter_table(
TABLE *const altered_table,
my_core::Alter_inplace_info *const ha_alter_info) override;
bool commit_inplace_alter_table(TABLE* const altered_table,
bool
commit_inplace_alter_table(TABLE *const altered_table,
my_core::Alter_inplace_info *const ha_alter_info,
bool commit);
bool commit) override;
int finalize_bulk_load() __attribute__((__warn_unused_result__));
int finalize_bulk_load() MY_ATTRIBUTE((__warn_unused_result__));
void set_use_read_free_rpl(const char *const whitelist);
void set_skip_unique_check_tables(const char *const whitelist);
@@ -1055,8 +1118,7 @@ public:
Helper class for in-place alter, for storing handler context between inplace
alter calls
*/
struct Rdb_inplace_alter_ctx : public my_core::inplace_alter_handler_ctx
{
struct Rdb_inplace_alter_ctx : public my_core::inplace_alter_handler_ctx {
/* The new table definition */
Rdb_tbl_def *const m_new_tdef;
@@ -1089,17 +1151,13 @@ struct Rdb_inplace_alter_ctx : public my_core::inplace_alter_handler_ctx
std::shared_ptr<Rdb_key_def> *new_key_descr, uint old_n_keys,
uint new_n_keys,
std::unordered_set<std::shared_ptr<Rdb_key_def>> added_indexes,
std::unordered_set<GL_INDEX_ID> dropped_index_ids,
uint n_added_keys, uint n_dropped_keys) :
my_core::inplace_alter_handler_ctx(), m_new_tdef(new_tdef),
std::unordered_set<GL_INDEX_ID> dropped_index_ids, uint n_added_keys,
uint n_dropped_keys)
: my_core::inplace_alter_handler_ctx(), m_new_tdef(new_tdef),
m_old_key_descr(old_key_descr), m_new_key_descr(new_key_descr),
m_old_n_keys(old_n_keys), m_new_n_keys(new_n_keys),
m_added_indexes(added_indexes),
m_dropped_index_ids(dropped_index_ids),
m_n_added_keys(n_added_keys),
m_n_dropped_keys(n_dropped_keys)
{
}
m_added_indexes(added_indexes), m_dropped_index_ids(dropped_index_ids),
m_n_added_keys(n_added_keys), m_n_dropped_keys(n_dropped_keys) {}
~Rdb_inplace_alter_ctx() {}

View File

@@ -32,27 +32,31 @@ enum RDB_IO_ERROR_TYPE {
RDB_IO_ERROR_TX_COMMIT,
RDB_IO_ERROR_DICT_COMMIT,
RDB_IO_ERROR_BG_THREAD,
RDB_IO_ERROR_GENERAL
RDB_IO_ERROR_GENERAL,
RDB_IO_ERROR_LAST
};
void rdb_handle_io_error(rocksdb::Status status, RDB_IO_ERROR_TYPE err_type);
const char *get_rdb_io_error_string(const RDB_IO_ERROR_TYPE err_type);
void rdb_handle_io_error(const rocksdb::Status status,
const RDB_IO_ERROR_TYPE err_type);
int rdb_normalize_tablename(const std::string &tablename, std::string *str)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int rdb_split_normalized_tablename(const std::string &fullname, std::string *db,
std::string *table = nullptr,
std::string *partition = nullptr)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
std::vector<std::string> rdb_get_open_table_names(void);
int rdb_get_table_perf_counters(const char *tablename,
Rdb_perf_counters *counters)
__attribute__((__nonnull__(2)));
MY_ATTRIBUTE((__nonnull__(2)));
void rdb_get_global_perf_counters(Rdb_perf_counters *counters)
__attribute__((__nonnull__(1)));
MY_ATTRIBUTE((__nonnull__(1)));
void rdb_queue_save_stats_request();
@@ -69,14 +73,14 @@ rocksdb::BlockBasedTableOptions& rdb_get_table_options();
class Rdb_dict_manager;
Rdb_dict_manager *rdb_get_dict_manager(void)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
class Rdb_ddl_manager;
Rdb_ddl_manager *rdb_get_ddl_manager(void)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
class Rdb_binlog_manager;
Rdb_binlog_manager *rdb_get_binlog_manager(void)
__attribute__((__warn_unused_result__));
MY_ATTRIBUTE((__warn_unused_result__));
} // namespace myrocks

View File

@@ -21,13 +21,10 @@
namespace myrocks {
class Rdb_logger : public rocksdb::Logger
{
class Rdb_logger : public rocksdb::Logger {
public:
void Logv(const rocksdb::InfoLogLevel log_level,
const char* format,
va_list ap) override
{
void Logv(const rocksdb::InfoLogLevel log_level, const char *format,
va_list ap) override {
DBUG_ASSERT(format != nullptr);
enum loglevel mysql_log_level;
@@ -54,15 +51,13 @@ class Rdb_logger : public rocksdb::Logger
error_log_print(mysql_log_level, f.c_str(), ap);
}
void Logv(const char* format, va_list ap) override
{
void Logv(const char *format, va_list ap) override {
DBUG_ASSERT(format != nullptr);
// If no level is specified, it is by default at information level
Logv(rocksdb::InfoLogLevel::INFO_LEVEL, format, ap);
}
void SetRocksDBLogger(const std::shared_ptr<rocksdb::Logger> logger)
{
void SetRocksDBLogger(const std::shared_ptr<rocksdb::Logger> logger) {
m_logger = logger;
}

View File

@@ -4,20 +4,20 @@ CREATE DATABASE mysqlslap;
USE mysqlslap;
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
# 2PC enabled, MyRocks durability enabled
SET GLOBAL rocksdb_disable_2pc=0;
SET GLOBAL rocksdb_enable_2pc=0;
SET GLOBAL rocksdb_write_sync=1;
## 2PC + durability + single thread
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
select case when variable_value-@c = 1000 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
case when variable_value-@c = 1000 then 'true' else 'false' end
true
false
## 2PC + durability + group commit
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
select case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true' else 'false' end
true
false
# 2PC enabled, MyRocks durability disabled
SET GLOBAL rocksdb_disable_2pc=0;
SET GLOBAL rocksdb_enable_2pc=0;
SET GLOBAL rocksdb_write_sync=0;
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
select case when variable_value-@c = 0 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
@@ -28,17 +28,17 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
case when variable_value-@c = 0 then 'true' else 'false' end
true
# 2PC disabled, MyRocks durability enabled
SET GLOBAL rocksdb_disable_2pc=1;
SET GLOBAL rocksdb_enable_2pc=1;
SET GLOBAL rocksdb_write_sync=1;
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
select case when variable_value-@c = 0 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
case when variable_value-@c = 0 then 'true' else 'false' end
true
false
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
select case when variable_value-@c = 0 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
case when variable_value-@c = 0 then 'true' else 'false' end
true
SET GLOBAL rocksdb_disable_2pc=1;
false
SET GLOBAL rocksdb_enable_2pc=1;
SET GLOBAL rocksdb_write_sync=0;
DROP TABLE t1;
DROP DATABASE mysqlslap;

View File

@@ -60,11 +60,8 @@ CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i), KEY(j)) ENGINE = ROCKSDB
# crash_during_index_creation_partition
flush logs;
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
# expected assertion failure from sql layer here for alter rollback
call mtr.add_suppression("Assertion `0' failed.");
call mtr.add_suppression("Attempting backtrace. You can use the following information to find out");
ALTER TABLE t1 ADD INDEX kij(i,j), ALGORITHM=INPLACE;
ERROR HY000: Lost connection to MySQL server during query
ERROR HY000: Intentional failure in inplace alter occurred.
SET SESSION debug="-d,myrocks_simulate_index_create_rollback";
SHOW CREATE TABLE t1;
Table Create Table

View File

@@ -0,0 +1,89 @@
drop table if exists t1;
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, 6);
INSERT INTO t1 (a, b) VALUES (3, 7);
INSERT INTO t1 (a,b) VALUES (4,5);
ALTER TABLE t1 ADD UNIQUE INDEX kb(b), ALGORITHM=INPLACE;
ERROR 23000: Duplicate entry '5' for key 'kb'
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, 6);
INSERT INTO t1 (a, b) VALUES (3, 7);
ALTER TABLE t1 ADD UNIQUE INDEX kb(b), ALGORITHM=INPLACE;
INSERT INTO t1 (a,b) VALUES (4,5);
ERROR 23000: Duplicate entry '5' for key 'kb'
INSERT INTO t1 (a,b) VALUES (5,8);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
UNIQUE KEY `kb` (`b`)
) ENGINE=ROCKSDB DEFAULT CHARSET=latin1
SELECT * FROM t1 FORCE INDEX(kb);
a b
1 5
2 6
3 7
5 8
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, NULL);
INSERT INTO t1 (a, b) VALUES (3, NULL);
ALTER TABLE t1 ADD UNIQUE INDEX kb(b), ALGORITHM=INPLACE;
INSERT INTO t1 (a, b) VALUES (4, NULL);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
UNIQUE KEY `kb` (`b`)
) ENGINE=ROCKSDB DEFAULT CHARSET=latin1
SELECT COUNT(*) FROM t1 FORCE INDEX(kb);
COUNT(*)
4
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a,b,c) VALUES (1,1,NULL);
INSERT INTO t1 (a,b,c) VALUES (2,1,NULL);
INSERT INTO t1 (a,b,c) VALUES (3,1,NULL);
INSERT INTO t1 (a,b,c) VALUES (4,1,5);
ALTER TABLE t1 ADD UNIQUE INDEX kbc(b,c), ALGORITHM=INPLACE;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`a`),
UNIQUE KEY `kbc` (`b`,`c`)
) ENGINE=ROCKSDB DEFAULT CHARSET=latin1
SELECT COUNT(*) FROM t1 FORCE INDEX(kbc);
COUNT(*)
4
DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, 6);
INSERT INTO t1 (a, b) VALUES (3, 7);
ALTER TABLE t1 ADD UNIQUE INDEX kb(b);
ERROR HY000: Unique index support is disabled when the table has no primary key.
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=ROCKSDB DEFAULT CHARSET=latin1
DROP TABLE t1;

View File

@@ -10,19 +10,19 @@ SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
WHERE INDEX_NUMBER =
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
WHERE TABLE_NAME = 't1' AND INDEX_NAME = "PRIMARY");
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS
# # SSTNAME 5 # # # # #
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
# # SSTNAME 5 # # # # # 5
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
WHERE INDEX_NUMBER =
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
WHERE TABLE_NAME = 't1' AND INDEX_NAME = "j");
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS
# # SSTNAME 5 # # # # #
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
# # SSTNAME 5 # # # # # 5,5
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
WHERE INDEX_NUMBER =
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
WHERE TABLE_NAME = 't2' AND INDEX_NAME = "PRIMARY");
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS
# # SSTNAME 4 # # # # #
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
# # SSTNAME 4 # # # # # 4
DROP TABLE t1;
DROP TABLE t2;

View File

@@ -9,6 +9,7 @@ CF_FLAGS 1 __system__ [0]
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
count(*)
3
select VALUE into @keysIn from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
CREATE TABLE t1 (i1 INT, i2 INT, PRIMARY KEY (i1)) ENGINE = ROCKSDB;
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
@@ -22,6 +23,11 @@ CF_FLAGS 1 __system__ [0]
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
count(*)
6
set global rocksdb_force_flush_memtable_now = true;
set global rocksdb_compact_cf='default';
select case when VALUE-@keysIn >= 3 then 'true' else 'false' end from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
case when VALUE-@keysIn >= 3 then 'true' else 'false' end
true
CREATE INDEX tindex1 on t1 (i1);
CREATE INDEX tindex2 on t1 (i2);
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where TYPE = 'CF_FLAGS';

View File

@@ -121,7 +121,7 @@ a b
5 loaded
7 test
DROP TABLE t1;
set session rocksdb_skip_unique_check=1;
set session unique_checks=0;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a INT, b CHAR(8), pk INT AUTO_INCREMENT PRIMARY KEY) ENGINE=rocksdb;
LOAD DATA INFILE '<DATADIR>/se_loaddata.dat' INTO TABLE t1

View File

@@ -0,0 +1,11 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a int primary key) ENGINE=ROCKSDB;
insert into t1 values (1);
set global rocksdb_force_flush_memtable_now=1;
select * from t1 where a = 1;
a
1
select * from t1 where a = 1;
a
1
drop table t1;

View File

@@ -890,8 +890,8 @@ rocksdb_deadlock_detect OFF
rocksdb_debug_optimizer_no_zero_cardinality ON
rocksdb_default_cf_options
rocksdb_delete_obsolete_files_period_micros 21600000000
rocksdb_disable_2pc ON
rocksdb_disabledatasync OFF
rocksdb_enable_2pc ON
rocksdb_enable_bulk_load_api ON
rocksdb_enable_thread_tracking OFF
rocksdb_enable_write_thread_adaptive_yield OFF
@@ -924,17 +924,17 @@ rocksdb_override_cf_options
rocksdb_paranoid_checks ON
rocksdb_pause_background_work ON
rocksdb_perf_context_level 0
rocksdb_persistent_cache_path
rocksdb_persistent_cache_size 0
rocksdb_pin_l0_filter_and_index_blocks_in_cache ON
rocksdb_print_snapshot_conflict_queries OFF
rocksdb_rate_limiter_bytes_per_sec 0
rocksdb_read_free_rpl_tables
rocksdb_records_in_range 50
rocksdb_rpl_skip_tx_api OFF
rocksdb_seconds_between_stat_computes 3600
rocksdb_signal_drop_index_thread OFF
rocksdb_skip_bloom_filter_on_read OFF
rocksdb_skip_fill_cache OFF
rocksdb_skip_unique_check OFF
rocksdb_skip_unique_check_tables .*
rocksdb_stats_dump_period_sec 600
rocksdb_store_row_debug_checksums OFF
@@ -2231,7 +2231,7 @@ DROP DATABASE test_db;
# Issue #143: Split rocksdb_bulk_load option into two
#
CREATE TABLE t1 (id int primary key, value int) engine=RocksDB;
SET rocksdb_skip_unique_check=1;
SET unique_checks=0;
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(1, 3);
@@ -2243,7 +2243,7 @@ INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1;
ERROR HY000: When unique checking is disabled in MyRocks, INSERT,UPDATE,LOAD statements with clauses that update or replace the key (i.e. INSERT ON DUPLICATE KEY UPDATE, REPLACE) are not allowed. Query: INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1
TRUNCATE TABLE t1;
SET @save_rocksdb_bulk_load_size= @@rocksdb_bulk_load_size;
SET rocksdb_skip_unique_check=0;
SET unique_checks=1;
SET rocksdb_commit_in_the_middle=1;
SET rocksdb_bulk_load_size=10;
BEGIN;

View File

@@ -6,9 +6,9 @@ Note #### Storing MySQL user name or password information in the master info rep
DROP TABLE IF EXISTS t1;
include/stop_slave.inc
create table t1 (a int) engine=rocksdb;
show variables like 'rocksdb_rpl_skip_tx_api';
show variables like 'rpl_skip_tx_api';
Variable_name Value
rocksdb_rpl_skip_tx_api ON
rpl_skip_tx_api ON
include/start_slave.inc
found
DROP TABLE t1;

View File

@@ -183,3 +183,24 @@ ERROR 23000: Duplicate entry '1-1' for key 'PRIMARY'
INSERT INTO t2 VALUES (2,1);
ERROR 23000: Duplicate entry '1' for key 'a'
DROP TABLE t2;
#
# Issue #491 (https://github.com/facebook/mysql-5.6/issues/491)
#
CREATE TABLE t (a BLOB, PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
INSERT INTO t VALUES('a');
CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text
test.t check status OK
DROP TABLE t;
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a), UNIQUE KEY (a(1))) engine=rocksdb;
INSERT INTO t VALUES('a');
CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text
test.t check status OK
DROP TABLE t;
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
INSERT INTO t VALUES('a');
CHECK TABLE t EXTENDED;
Table Op Msg_type Msg_text
test.t check status OK
DROP TABLE t;

View File

@@ -13,7 +13,7 @@ USE mysqlslap;
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
--echo # 2PC enabled, MyRocks durability enabled
SET GLOBAL rocksdb_disable_2pc=0;
SET GLOBAL rocksdb_enable_2pc=0;
SET GLOBAL rocksdb_write_sync=1;
--echo ## 2PC + durability + single thread
@@ -28,7 +28,7 @@ select case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true'
--echo # 2PC enabled, MyRocks durability disabled
SET GLOBAL rocksdb_disable_2pc=0;
SET GLOBAL rocksdb_enable_2pc=0;
SET GLOBAL rocksdb_write_sync=0;
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
@@ -41,7 +41,7 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
--echo # 2PC disabled, MyRocks durability enabled
SET GLOBAL rocksdb_disable_2pc=1;
SET GLOBAL rocksdb_enable_2pc=1;
SET GLOBAL rocksdb_write_sync=1;
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
@@ -58,7 +58,7 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
SET GLOBAL rocksdb_disable_2pc=1;
SET GLOBAL rocksdb_enable_2pc=1;
SET GLOBAL rocksdb_write_sync=0;
DROP TABLE t1;
DROP DATABASE mysqlslap;

View File

@@ -89,22 +89,11 @@ while ($i <= $max) {
--echo # crash_during_index_creation_partition
flush logs;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
--echo # expected assertion failure from sql layer here for alter rollback
call mtr.add_suppression("Assertion `0' failed.");
call mtr.add_suppression("Attempting backtrace. You can use the following information to find out");
--error 2013
--error 1105
ALTER TABLE t1 ADD INDEX kij(i,j), ALGORITHM=INPLACE;
--enable_reconnect
--source include/wait_until_connected_again.inc
SET SESSION debug="-d,myrocks_simulate_index_create_rollback";
SHOW CREATE TABLE t1;
# here, the index numbers should be higher because previously 4 index numbers

View File

@@ -0,0 +1,82 @@
--source include/have_rocksdb.inc
--source include/have_debug.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
# test adding duplicate value before unique index
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, 6);
INSERT INTO t1 (a, b) VALUES (3, 7);
INSERT INTO t1 (a,b) VALUES (4,5);
# should cause error here, duplicate value on b
--error 1062
ALTER TABLE t1 ADD UNIQUE INDEX kb(b), ALGORITHM=INPLACE;
SHOW CREATE TABLE t1;
DROP TABLE t1;
# test dup value AFTER unique index
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, 6);
INSERT INTO t1 (a, b) VALUES (3, 7);
ALTER TABLE t1 ADD UNIQUE INDEX kb(b), ALGORITHM=INPLACE;
# should error here, duplicate value on b
--error 1062
INSERT INTO t1 (a,b) VALUES (4,5);
# should succeed
INSERT INTO t1 (a,b) VALUES (5,8);
SHOW CREATE TABLE t1;
SELECT * FROM t1 FORCE INDEX(kb);
DROP TABLE t1;
# test what happens when duplicate nulls exist
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, NULL);
INSERT INTO t1 (a, b) VALUES (3, NULL);
# should pass, because in MySQL we allow multiple NULLS in unique key
ALTER TABLE t1 ADD UNIQUE INDEX kb(b), ALGORITHM=INPLACE;
INSERT INTO t1 (a, b) VALUES (4, NULL);
SHOW CREATE TABLE t1;
SELECT COUNT(*) FROM t1 FORCE INDEX(kb);
DROP TABLE t1;
## test case with multi-part key with nulls
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY ka(a)) ENGINE=RocksDB;
INSERT INTO t1 (a,b,c) VALUES (1,1,NULL);
INSERT INTO t1 (a,b,c) VALUES (2,1,NULL);
INSERT INTO t1 (a,b,c) VALUES (3,1,NULL);
INSERT INTO t1 (a,b,c) VALUES (4,1,5);
# should pass
ALTER TABLE t1 ADD UNIQUE INDEX kbc(b,c), ALGORITHM=INPLACE;
SHOW CREATE TABLE t1;
SELECT COUNT(*) FROM t1 FORCE INDEX(kbc);
DROP TABLE t1;
## test case with table w/ no primary key, and we try to add unique key
CREATE TABLE t1 (a INT, b INT) ENGINE=RocksDB;
INSERT INTO t1 (a, b) VALUES (1, 5);
INSERT INTO t1 (a, b) VALUES (2, 6);
INSERT INTO t1 (a, b) VALUES (3, 7);
# should fail, can't add unique index on table w/ no pk
--error 1105
ALTER TABLE t1 ADD UNIQUE INDEX kb(b);
SHOW CREATE TABLE t1;
DROP TABLE t1;

View File

@@ -12,6 +12,8 @@ DROP TABLE IF EXISTS t3;
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
select VALUE into @keysIn from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
CREATE TABLE t1 (i1 INT, i2 INT, PRIMARY KEY (i1)) ENGINE = ROCKSDB;
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
@@ -21,6 +23,10 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
set global rocksdb_force_flush_memtable_now = true;
set global rocksdb_compact_cf='default';
select case when VALUE-@keysIn >= 3 then 'true' else 'false' end from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
CREATE INDEX tindex1 on t1 (i1);
--let $start_max_index_id = query_get_value(SELECT * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where type = 'MAX_INDEX_ID', VALUE, 1)

View File

@@ -3,6 +3,5 @@
let $skip_unique_check = 0;
--source loaddata.inc
let $skip_unique_check = 1;
set session rocksdb_skip_unique_check=1;
set session unique_checks=0;
--source loaddata.inc

View File

@@ -0,0 +1,41 @@
--source include/have_rocksdb.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
--let $_server_id= `SELECT @@server_id`
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect
--let $_cache_file_name= $MYSQLTEST_VARDIR/tmp/persistent_cache
--exec echo "wait" >$_expect_file_name
# restart server with correct parameters
shutdown_server 10;
--exec echo "restart:--rocksdb_persistent_cache_path=$_cache_file_name --rocksdb_persistent_cache_size=1000000000" >$_expect_file_name
--sleep 5
--enable_reconnect
--source include/wait_until_connected_again.inc
--disable_reconnect
# insert values and flush out of memtable
CREATE TABLE t1 (a int primary key) ENGINE=ROCKSDB;
insert into t1 values (1);
set global rocksdb_force_flush_memtable_now=1;
# pull data through cache
select * from t1 where a = 1;
# restart server to re-read cache
--exec echo "wait" >$_expect_file_name
shutdown_server 10;
--exec echo "restart:--rocksdb_persistent_cache_path=$_cache_file_name --rocksdb_persistent_cache_size=1000000000" >$_expect_file_name
--sleep 5
--enable_reconnect
--source include/wait_until_connected_again.inc
--disable_reconnect
# pull values from cache again
select * from t1 where a = 1;
drop table t1;

View File

@@ -1768,7 +1768,7 @@ DROP DATABASE test_db;
--echo # Issue #143: Split rocksdb_bulk_load option into two
--echo #
CREATE TABLE t1 (id int primary key, value int) engine=RocksDB;
SET rocksdb_skip_unique_check=1;
SET unique_checks=0;
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(1, 3);
@@ -1779,7 +1779,7 @@ REPLACE INTO t1 VALUES(4, 4);
INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1;
TRUNCATE TABLE t1;
SET @save_rocksdb_bulk_load_size= @@rocksdb_bulk_load_size;
SET rocksdb_skip_unique_check=0;
SET unique_checks=1;
SET rocksdb_commit_in_the_middle=1;
SET rocksdb_bulk_load_size=10;
BEGIN;

View File

@@ -5,4 +5,4 @@ binlog_format=row
[mysqld.2]
binlog_format=row
slave_parallel_workers=1
rocksdb_rpl_skip_tx_api=ON
rpl_skip_tx_api=ON

View File

@@ -17,7 +17,7 @@ while ($aa < 1000) {
--enable_query_log
connection slave;
show variables like 'rocksdb_rpl_skip_tx_api';
show variables like 'rpl_skip_tx_api';
--source include/start_slave.inc
--let $it=0

View File

@@ -31,3 +31,21 @@ INSERT INTO t2 VALUES (1,1);
--error ER_DUP_ENTRY
INSERT INTO t2 VALUES (2,1);
DROP TABLE t2;
--echo #
--echo # Issue #491 (https://github.com/facebook/mysql-5.6/issues/491)
--echo #
CREATE TABLE t (a BLOB, PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
INSERT INTO t VALUES('a');
CHECK TABLE t EXTENDED;
DROP TABLE t;
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a), UNIQUE KEY (a(1))) engine=rocksdb;
INSERT INTO t VALUES('a');
CHECK TABLE t EXTENDED;
DROP TABLE t;
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
INSERT INTO t VALUES('a');
CHECK TABLE t EXTENDED;
DROP TABLE t;

View File

@@ -0,0 +1,2 @@
src_data_dir="${MYSQLTEST_VARDIR}/mysqld.1/data/"
python -c "import socket as s; sock = s.socket(s.AF_UNIX); sock.bind('${src_data_dir}/slocket')"

View File

@@ -0,0 +1,43 @@
set -e
# Insert 10 batches of 10 records each to a table with following schema:
# create table slocket.t1 (
# `id` int(10) not null auto_increment,
# `k` int(10),
# `data` varchar(2048),
# primary key (`id`),
# key (`k`)
# ) engine=innodb;
MAX_INSERTS=10
MAX_ROWS_PER_INSERT=10
insertData() {
for ((i=1; i<=$MAX_INSERTS; i++));
do
stmt='INSERT INTO slocket.t1 values'
for ((j=1; j<=$MAX_ROWS_PER_INSERT; j++));
do
k=$RANDOM
data=$(head -c 2048 /dev/urandom|tr -cd 'a-zA-Z0-9')
stmt=$stmt' (NULL, '$k', "'$data'")'
if [ $j -lt $MAX_ROWS_PER_INSERT ]; then
stmt=$stmt','
fi
done
stmt=$stmt';'
$MYSQL --defaults-group-suffix=.1 -e "$stmt"
done
}
NUM_PARALLEL_INSERTS=25
pids=()
for ((k=1; k<=$NUM_PARALLEL_INSERTS; k++));
do
insertData &
pids+=($!)
done
for ((k=1; k<=$NUM_PARALLEL_INSERTS; k++));
do
wait ${pids[k]}
done

View File

@@ -0,0 +1,2 @@
src_data_dir="${MYSQLTEST_VARDIR}/mysqld.1/data/"
rm "${src_data_dir}/slocket"

View File

@@ -0,0 +1,10 @@
connection server_1;
create database slocket;
create table slocket.t1 (
`id` int(10) not null auto_increment,
`k` int(10),
`data` varchar(2048),
primary key (`id`),
key (`k`)
) engine=rocksdb;

View File

@@ -39,6 +39,11 @@ elif [ "$STREAM_TYPE" == 'xbstream' ]; then
--stream=xbstream --checkpoint_dir=$checkpoint_dir 2> \
$COPY_LOG | xbstream -x \
--directory=$backup_dir"
elif [ "$STREAM_TYPE" == "xbstream_socket" ]; then
BACKUP_CMD="$MYSQL_MYROCKS_HOTBACKUP --user='root' --socket=${MASTER_MYSOCK} \
--stream=xbstream --checkpoint_dir=$checkpoint_dir 2> \
$COPY_LOG | xbstream -x \
--directory=$backup_dir"
else
BACKUP_CMD="$MYSQL_MYROCKS_HOTBACKUP --user='root' --stream=wdt \
--port=${MASTER_MYPORT} --destination=localhost --backup_dir=$backup_dir \

View File

@@ -0,0 +1,41 @@
include/rpl_init.inc [topology=none]
include/rpl_default_connections.inc
create database db1;
create table db1.t1 (
`id` int(10) not null auto_increment,
`k` int(10),
`data` varchar(2048),
primary key (`id`),
key (`k`)
) engine=rocksdb;
create database slocket;
create table slocket.t1 (
`id` int(10) not null auto_increment,
`k` int(10),
`data` varchar(2048),
primary key (`id`),
key (`k`)
) engine=rocksdb;
include/rpl_stop_server.inc [server_number=2]
myrocks_hotbackup copy phase
myrocks_hotbackup move-back phase
include/rpl_start_server.inc [server_number=2]
select count(*) from db1.t1;
count(*)
250000
select count(*) from slocket.t1;
count(*)
2500
drop database slocket;
drop database db1;
drop database slocket;
include/rpl_stop_server.inc [server_number=2]
myrocks_hotbackup copy phase
myrocks_hotbackup move-back phase
include/rpl_start_server.inc [server_number=2]
select count(*) from db1.t1;
count(*)
250000
drop database db1;
drop database db1;
include/rpl_end.inc

View File

@@ -0,0 +1,20 @@
include/rpl_init.inc [topology=none]
include/rpl_default_connections.inc
create database db1;
create table db1.t1 (
`id` int(10) not null auto_increment,
`k` int(10),
`data` varchar(2048),
primary key (`id`),
key (`k`)
) engine=rocksdb;
include/rpl_stop_server.inc [server_number=2]
myrocks_hotbackup copy phase
myrocks_hotbackup move-back phase
include/rpl_start_server.inc [server_number=2]
select count(*) from db1.t1;
count(*)
250000
drop database db1;
drop database db1;
include/rpl_end.inc

View File

@@ -0,0 +1,46 @@
source suite/rocksdb_hotbackup/include/setup.inc;
source suite/rocksdb_hotbackup/include/setup_slocket.inc;
--exec suite/rocksdb_hotbackup/include/load_data.sh 2>&1
--exec suite/rocksdb_hotbackup/include/load_data_slocket.sh 2>&1
--let $rpl_server_number= 2
--source include/rpl_stop_server.inc
--exec suite/rocksdb_hotbackup/include/stream_run.sh 2>&1
--let $rpl_server_number= 2
--source include/rpl_start_server.inc
connection server_2;
select count(*) from db1.t1;
select count(*) from slocket.t1;
connection server_1;
drop database slocket;
connection server_2;
drop database db1;
drop database slocket;
--exec sleep 2
--exec suite/rocksdb_hotbackup/include/create_slocket_socket.sh 2>&1
--let $rpl_server_number= 2
--source include/rpl_stop_server.inc
--exec suite/rocksdb_hotbackup/include/stream_run.sh 2>&1
--let $rpl_server_number= 2
--source include/rpl_start_server.inc
connection server_2;
select count(*) from db1.t1;
connection server_1;
drop database db1;
connection server_2;
drop database db1;
--exec suite/rocksdb_hotbackup/include/remove_slocket_socket.sh 2>&1
source suite/rocksdb_hotbackup/include/cleanup.inc;

View File

@@ -0,0 +1,22 @@
source suite/rocksdb_hotbackup/include/setup.inc;
--exec suite/rocksdb_hotbackup/include/load_data.sh 2>&1
--let $rpl_server_number= 2
--source include/rpl_stop_server.inc
--exec STREAM_TYPE=xbstream_socket suite/rocksdb_hotbackup/include/stream_run.sh 2>&1
--let $rpl_server_number= 2
--source include/rpl_start_server.inc
connection server_2;
select count(*) from db1.t1;
connection server_1;
drop database db1;
connection server_2;
drop database db1;
source suite/rocksdb_hotbackup/include/cleanup.inc;

View File

@@ -1,5 +1,5 @@
DROP TABLE IF EXISTS t1;
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
create table t1 (a int primary key, b int, c varchar(255)) engine=rocksdb;
'con1'
SET SESSION debug="d,crash_commit_after_log";
@@ -7,11 +7,11 @@ SET DEBUG_SYNC='rocksdb.prepared SIGNAL parked WAIT_FOR go';
insert into t1 values (1, 1, "iamtheogthealphaandomega");;
'con2'
insert into t1 values (2, 1, "i_am_just_here_to_trigger_a_flush");
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
SET GLOBAL ROCKSDB_WRITE_SYNC = OFF;
SET GLOBAL SYNC_BINLOG = 0;
SET DEBUG_SYNC='now WAIT_FOR parked';
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
SET GLOBAL ROCKSDB_WRITE_SYNC = ON;
SET GLOBAL SYNC_BINLOG = 1;
insert into t1 values (1000000, 1, "i_am_just_here_to_trigger_a_flush");

View File

@@ -1,18 +1,18 @@
DROP TABLE IF EXISTS t1;
create table t1 (a int primary key, msg varchar(255)) engine=rocksdb;
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
SET SESSION debug="d,crash_commit_after_prepare";
insert into t1 values (1, 'dogz');
select * from t1;
a msg
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
SET SESSION debug="d,crash_commit_after_log";
insert into t1 values (2, 'catz'), (3, 'men');
select * from t1;
a msg
2 catz
3 men
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
SET SESSION debug="d,crash_commit_after";
insert into t1 values (4, 'cars'), (5, 'foo');
select * from t1;
@@ -21,7 +21,7 @@ a msg
3 men
4 cars
5 foo
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
SET SESSION debug="d,crash_commit_after_log";
insert into t1 values (6, 'shipz'), (7, 'tankz');
select * from t1;
@@ -30,7 +30,7 @@ a msg
3 men
4 cars
5 foo
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
SET SESSION debug="d,crash_commit_after";
insert into t1 values (8, 'space'), (9, 'time');
select * from t1;

View File

@@ -0,0 +1,27 @@
include/master-slave.inc
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
[connection master]
call mtr.add_suppression("Master's binlog format is not ROW but rpl_skip_tx_api is enabled on the slave");
set global rpl_skip_tx_api=ON;
set global rocksdb_unsafe_for_binlog=1;
create table t1(a int);
set session binlog_format=STATEMENT;
insert into t1 values(1);
include/wait_for_slave_sql_error.inc [errno=1756]
Last_SQL_Error = 'Master's binlog format is not ROW but rpl_skip_tx_api is enabled on the slave. rpl_skip_tx_api recovery should only be used when master's binlog format is ROW.'
"Table after error"
select * from t1;
a
set global rpl_skip_tx_api=OFF;
include/start_slave.inc
include/sync_slave_sql_with_master.inc
"Table after error fixed"
select * from t1;
a
1
drop table t1;
set global rocksdb_unsafe_for_binlog=0;
set global rpl_skip_tx_api=0;
include/rpl_end.inc

View File

@@ -10,7 +10,7 @@
DROP TABLE IF EXISTS t1;
--enable_warnings
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
create table t1 (a int primary key, b int, c varchar(255)) engine=rocksdb;
connect (con1, localhost, root,,);
@@ -35,7 +35,7 @@ insert into t1 values (2, 1, "i_am_just_here_to_trigger_a_flush");
# Disable 2PC and syncing for faster inserting of dummy rows
# These rows only purpose is to rotate the binlog
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
SET GLOBAL ROCKSDB_WRITE_SYNC = OFF;
SET GLOBAL SYNC_BINLOG = 0;
@@ -50,7 +50,7 @@ while ($pk < 1000000) {
# re-enable 2PC an syncing then write to trigger a flush
# before we trigger the crash to simulate full-durability
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
SET GLOBAL ROCKSDB_WRITE_SYNC = ON;
SET GLOBAL SYNC_BINLOG = 1;

View File

@@ -2,8 +2,10 @@
[mysqld.1]
log_slave_updates
rocksdb_enable_2pc=OFF
[mysqld.2]
relay_log_recovery=1
relay_log_info_repository=TABLE
log_slave_updates
rocksdb_enable_2pc=OFF

View File

@@ -4,6 +4,7 @@
log_slave_updates
gtid_mode=ON
enforce_gtid_consistency=ON
rocksdb_enable_2pc=OFF
[mysqld.2]
sync_relay_log_info=100
@@ -12,3 +13,4 @@ relay_log_info_repository=FILE
log_slave_updates
gtid_mode=ON
enforce_gtid_consistency=ON
rocksdb_enable_2pc=OFF

View File

@@ -8,7 +8,7 @@ DROP TABLE IF EXISTS t1;
create table t1 (a int primary key, msg varchar(255)) engine=rocksdb;
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug="d,crash_commit_after_prepare";
--error 0,2013
@@ -17,7 +17,7 @@ insert into t1 values (1, 'dogz');
--source include/wait_until_connected_again.inc
select * from t1;
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug="d,crash_commit_after_log";
--error 0,2013
@@ -26,7 +26,7 @@ insert into t1 values (2, 'catz'), (3, 'men');
--source include/wait_until_connected_again.inc
select * from t1;
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug="d,crash_commit_after";
--error 0,2013
@@ -35,7 +35,7 @@ insert into t1 values (4, 'cars'), (5, 'foo');
--source include/wait_until_connected_again.inc
select * from t1;
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug="d,crash_commit_after_log";
--error 0,2013
@@ -44,7 +44,7 @@ insert into t1 values (6, 'shipz'), (7, 'tankz');
--source include/wait_until_connected_again.inc
select * from t1;
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
SET SESSION debug="d,crash_commit_after";
--error 0,2013

View File

@@ -0,0 +1,2 @@
--gtid_mode=ON --enforce_gtid_consistency --log_slave_updates
--binlog_format=STATEMENT --default-storage-engine=rocksdb

View File

@@ -0,0 +1,2 @@
--gtid_mode=ON --enforce_gtid_consistency --log_slave_updates
--sync_binlog=1000 --relay_log_recovery=1 --default-storage-engine=rocksdb

View File

@@ -0,0 +1,51 @@
# Checks if the slave stops executing transactions when master's binlog format
# is STATEMENT but rpl_skip_tx_api is enabled
-- source include/master-slave.inc
call mtr.add_suppression("Master's binlog format is not ROW but rpl_skip_tx_api is enabled on the slave");
connection slave;
let $old_rpl_skip_tx_api= `SELECT @@global.rpl_skip_tx_api`;
set global rpl_skip_tx_api=ON;
connection master;
let $old_rocksdb_unsafe_for_binlog= `SELECT @@global.rocksdb_unsafe_for_binlog`;
set global rocksdb_unsafe_for_binlog=1;
create table t1(a int);
set session binlog_format=STATEMENT;
insert into t1 values(1);
# Wait till we hit the binlog format mismatch error
connection slave;
let $slave_sql_errno= convert_error(ER_MTS_INCONSISTENT_DATA); # 1756
let $show_slave_sql_error= 1;
source include/wait_for_slave_sql_error.inc;
# Print table
connection slave;
echo "Table after error";
select * from t1;
connection slave;
# Turn off rpl_skip_tx_api and start the slave again
set global rpl_skip_tx_api=OFF;
source include/start_slave.inc;
connection slave;
source include/sync_slave_sql_with_master.inc;
connection slave;
# Print table again
echo "Table after error fixed";
select * from t1;
# Cleanup
connection master;
drop table t1;
eval set global rocksdb_unsafe_for_binlog=$old_rocksdb_unsafe_for_binlog;
sync_slave_with_master;
connection slave;
eval set global rpl_skip_tx_api=$old_rpl_skip_tx_api;
-- source include/rpl_end.inc

View File

@@ -9,5 +9,7 @@ There should be *no* long test name listed below:
select variable_name as `There should be *no* variables listed below:` from t2
left join t1 on variable_name=test_name where test_name is null ORDER BY variable_name;
There should be *no* variables listed below:
ROCKSDB_ENABLE_2PC
ROCKSDB_ENABLE_2PC
drop table t1;
drop table t2;

View File

@@ -6,70 +6,70 @@ INSERT INTO valid_values VALUES('off');
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
INSERT INTO invalid_values VALUES('\'bbb\'');
SET @start_global_value = @@global.ROCKSDB_DISABLE_2PC;
SET @start_global_value = @@global.ROCKSDB_ENABLE_2PC;
SELECT @start_global_value;
@start_global_value
1
'# Setting to valid values in global scope#'
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 1"
SET @@global.ROCKSDB_DISABLE_2PC = 1;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 1"
SET @@global.ROCKSDB_ENABLE_2PC = 1;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 0"
SET @@global.ROCKSDB_DISABLE_2PC = 0;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 0"
SET @@global.ROCKSDB_ENABLE_2PC = 0;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to on"
SET @@global.ROCKSDB_DISABLE_2PC = on;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to on"
SET @@global.ROCKSDB_ENABLE_2PC = on;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to off"
SET @@global.ROCKSDB_DISABLE_2PC = off;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to off"
SET @@global.ROCKSDB_ENABLE_2PC = off;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Trying to set variable @@session.ROCKSDB_DISABLE_2PC to 444. It should fail because it is not session."
SET @@session.ROCKSDB_DISABLE_2PC = 444;
ERROR HY000: Variable 'rocksdb_disable_2pc' is a GLOBAL variable and should be set with SET GLOBAL
"Trying to set variable @@session.ROCKSDB_ENABLE_2PC to 444. It should fail because it is not session."
SET @@session.ROCKSDB_ENABLE_2PC = 444;
ERROR HY000: Variable 'rocksdb_enable_2pc' is a GLOBAL variable and should be set with SET GLOBAL
'# Testing with invalid values in global scope #'
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 'aaa'"
SET @@global.ROCKSDB_DISABLE_2PC = 'aaa';
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 'aaa'"
SET @@global.ROCKSDB_ENABLE_2PC = 'aaa';
Got one of the listed errors
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 'bbb'"
SET @@global.ROCKSDB_DISABLE_2PC = 'bbb';
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 'bbb'"
SET @@global.ROCKSDB_ENABLE_2PC = 'bbb';
Got one of the listed errors
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
SET @@global.ROCKSDB_DISABLE_2PC = @start_global_value;
SELECT @@global.ROCKSDB_DISABLE_2PC;
@@global.ROCKSDB_DISABLE_2PC
SET @@global.ROCKSDB_ENABLE_2PC = @start_global_value;
SELECT @@global.ROCKSDB_ENABLE_2PC;
@@global.ROCKSDB_ENABLE_2PC
1
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -1,7 +1,46 @@
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES(64);
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'abc\'');
SET @start_global_value = @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
SELECT @start_global_value;
@start_global_value
1
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 444. It should fail because it is readonly."
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 444;
ERROR HY000: Variable 'rocksdb_max_background_compactions' is a read only variable
'# Setting to valid values in global scope#'
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 1"
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 1;
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = DEFAULT;
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
1
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 64"
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 64;
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
64
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = DEFAULT;
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
1
"Trying to set variable @@session.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 444. It should fail because it is not session."
SET @@session.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 444;
ERROR HY000: Variable 'rocksdb_max_background_compactions' is a GLOBAL variable and should be set with SET GLOBAL
'# Testing with invalid values in global scope #'
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 'abc'"
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 'abc';
Got one of the listed errors
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
1
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = @start_global_value;
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
1
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -0,0 +1,13 @@
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES('abc');
INSERT INTO valid_values VALUES('def');
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
SET @start_global_value = @@global.ROCKSDB_PERSISTENT_CACHE_PATH;
SELECT @start_global_value;
@start_global_value
"Trying to set variable @@global.ROCKSDB_PERSISTENT_CACHE_PATH to 444. It should fail because it is readonly."
SET @@global.ROCKSDB_PERSISTENT_CACHE_PATH = 444;
ERROR HY000: Variable 'rocksdb_persistent_cache_path' is a read only variable
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -0,0 +1,14 @@
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES(1024);
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
SET @start_global_value = @@global.ROCKSDB_PERSISTENT_CACHE_SIZE;
SELECT @start_global_value;
@start_global_value
0
"Trying to set variable @@global.ROCKSDB_PERSISTENT_CACHE_SIZE to 444. It should fail because it is readonly."
SET @@global.ROCKSDB_PERSISTENT_CACHE_SIZE = 444;
ERROR HY000: Variable 'rocksdb_persistent_cache_size' is a read only variable
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -1,68 +0,0 @@
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES(0);
INSERT INTO valid_values VALUES('on');
INSERT INTO valid_values VALUES('off');
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
SET @start_global_value = @@global.ROCKSDB_RPL_SKIP_TX_API;
SELECT @start_global_value;
@start_global_value
1
'# Setting to valid values in global scope#'
"Trying to set variable @@global.ROCKSDB_RPL_SKIP_TX_API to 1"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = 1;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = DEFAULT;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
"Trying to set variable @@global.ROCKSDB_RPL_SKIP_TX_API to 0"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = 0;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = DEFAULT;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
"Trying to set variable @@global.ROCKSDB_RPL_SKIP_TX_API to on"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = on;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = DEFAULT;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
"Trying to set variable @@global.ROCKSDB_RPL_SKIP_TX_API to off"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = off;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = DEFAULT;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
"Trying to set variable @@session.ROCKSDB_RPL_SKIP_TX_API to 444. It should fail because it is not session."
SET @@session.ROCKSDB_RPL_SKIP_TX_API = 444;
ERROR HY000: Variable 'rocksdb_rpl_skip_tx_api' is a GLOBAL variable and should be set with SET GLOBAL
'# Testing with invalid values in global scope #'
"Trying to set variable @@global.ROCKSDB_RPL_SKIP_TX_API to 'aaa'"
SET @@global.ROCKSDB_RPL_SKIP_TX_API = 'aaa';
Got one of the listed errors
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
SET @@global.ROCKSDB_RPL_SKIP_TX_API = @start_global_value;
SELECT @@global.ROCKSDB_RPL_SKIP_TX_API;
@@global.ROCKSDB_RPL_SKIP_TX_API
1
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -1,163 +0,0 @@
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(0);
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES('on');
INSERT INTO valid_values VALUES('off');
INSERT INTO valid_values VALUES('true');
INSERT INTO valid_values VALUES('false');
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
INSERT INTO invalid_values VALUES('\'bbb\'');
SET @start_global_value = @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
SELECT @start_global_value;
@start_global_value
0
SET @start_session_value = @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
SELECT @start_session_value;
@start_session_value
0
'# Setting to valid values in global scope#'
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to 0"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = 0;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to 1"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = 1;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to on"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = on;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to off"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = off;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to true"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = true;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
1
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to false"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = false;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Setting the global scope variable back to default"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
'# Setting to valid values in session scope#'
"Trying to set variable @@session.ROCKSDB_SKIP_UNIQUE_CHECK to 0"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = 0;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Setting the session scope variable back to default"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@session.ROCKSDB_SKIP_UNIQUE_CHECK to 1"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = 1;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
1
"Setting the session scope variable back to default"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@session.ROCKSDB_SKIP_UNIQUE_CHECK to on"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = on;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
1
"Setting the session scope variable back to default"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@session.ROCKSDB_SKIP_UNIQUE_CHECK to off"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = off;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Setting the session scope variable back to default"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@session.ROCKSDB_SKIP_UNIQUE_CHECK to true"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = true;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
1
"Setting the session scope variable back to default"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@session.ROCKSDB_SKIP_UNIQUE_CHECK to false"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = false;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Setting the session scope variable back to default"
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = DEFAULT;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
'# Testing with invalid values in global scope #'
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to 'aaa'"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = 'aaa';
Got one of the listed errors
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
"Trying to set variable @@global.ROCKSDB_SKIP_UNIQUE_CHECK to 'bbb'"
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = 'bbb';
Got one of the listed errors
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
SET @@global.ROCKSDB_SKIP_UNIQUE_CHECK = @start_global_value;
SELECT @@global.ROCKSDB_SKIP_UNIQUE_CHECK;
@@global.ROCKSDB_SKIP_UNIQUE_CHECK
0
SET @@session.ROCKSDB_SKIP_UNIQUE_CHECK = @start_session_value;
SELECT @@session.ROCKSDB_SKIP_UNIQUE_CHECK;
@@session.ROCKSDB_SKIP_UNIQUE_CHECK
0
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -10,7 +10,7 @@ CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
INSERT INTO invalid_values VALUES('\'bbb\'');
--let $sys_var=ROCKSDB_DISABLE_2PC
--let $sys_var=ROCKSDB_ENABLE_2PC
--let $read_only=0
--let $session=0
--let $sticky=1

View File

@@ -1,7 +1,16 @@
--source include/have_rocksdb.inc
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES(64);
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'abc\'');
--let $sys_var=ROCKSDB_MAX_BACKGROUND_COMPACTIONS
--let $read_only=1
--let $read_only=0
--let $session=0
--source suite/sys_vars/inc/rocksdb_sys_var.inc
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -0,0 +1,16 @@
--source include/have_rocksdb.inc
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES('abc');
INSERT INTO valid_values VALUES('def');
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
--let $sys_var=ROCKSDB_PERSISTENT_CACHE_PATH
--let $read_only=1
--let $session=0
--let $sticky=1
--source suite/sys_vars/inc/rocksdb_sys_var.inc
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -2,15 +2,13 @@
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES(0);
INSERT INTO valid_values VALUES('on');
INSERT INTO valid_values VALUES('off');
INSERT INTO valid_values VALUES(1024);
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
--let $sys_var=ROCKSDB_RPL_SKIP_TX_API
--let $read_only=0
--let $sys_var=ROCKSDB_PERSISTENT_CACHE_SIZE
--let $read_only=1
--let $session=0
--source suite/sys_vars/inc/rocksdb_sys_var.inc

View File

@@ -1,21 +0,0 @@
--source include/have_rocksdb.inc
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO valid_values VALUES(0);
INSERT INTO valid_values VALUES(1);
INSERT INTO valid_values VALUES('on');
INSERT INTO valid_values VALUES('off');
INSERT INTO valid_values VALUES('true');
INSERT INTO valid_values VALUES('false');
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
INSERT INTO invalid_values VALUES('\'aaa\'');
INSERT INTO invalid_values VALUES('\'bbb\'');
--let $sys_var=ROCKSDB_SKIP_UNIQUE_CHECK
--let $read_only=0
--let $session=1
--source suite/sys_vars/inc/rocksdb_sys_var.inc
DROP TABLE valid_values;
DROP TABLE invalid_values;

View File

@@ -41,21 +41,15 @@ std::atomic<uint64_t> rocksdb_num_sst_entry_merge(0);
std::atomic<uint64_t> rocksdb_num_sst_entry_other(0);
my_bool rocksdb_compaction_sequential_deletes_count_sd = false;
Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(
Rdb_ddl_manager* const ddl_manager,
Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
const Rdb_compact_params &params,
const uint32_t &cf_id,
const uint8_t &table_stats_sampling_pct
) :
m_cf_id(cf_id),
m_ddl_manager(ddl_manager),
m_last_stats(nullptr),
const uint8_t &table_stats_sampling_pct)
: m_cf_id(cf_id), m_ddl_manager(ddl_manager), m_last_stats(nullptr),
m_rows(0l), m_window_pos(0l), m_deleted_rows(0l), m_max_deleted_rows(0l),
m_file_size(0), m_params(params),
m_table_stats_sampling_pct(table_stats_sampling_pct),
m_seed(time(nullptr)),
m_card_adj_extra(1.)
{
m_seed(time(nullptr)), m_card_adj_extra(1.) {
DBUG_ASSERT(ddl_manager != nullptr);
// We need to adjust the index cardinality numbers based on the sampling
@@ -71,12 +65,11 @@ Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(
/*
This function is called by RocksDB for every key in the SST file
*/
rocksdb::Status
Rdb_tbl_prop_coll::AddUserKey(
const rocksdb::Slice& key, const rocksdb::Slice& value,
rocksdb::EntryType type, rocksdb::SequenceNumber seq,
uint64_t file_size
) {
rocksdb::Status Rdb_tbl_prop_coll::AddUserKey(const rocksdb::Slice &key,
const rocksdb::Slice &value,
rocksdb::EntryType type,
rocksdb::SequenceNumber seq,
uint64_t file_size) {
if (key.size() >= 4) {
AdjustDeletedRows(type);
@@ -88,10 +81,8 @@ Rdb_tbl_prop_coll::AddUserKey(
return rocksdb::Status::OK();
}
void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type)
{
if (m_params.m_window > 0)
{
void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type) {
if (m_params.m_window > 0) {
// record the "is deleted" flag into the sliding window
// the sliding window is implemented as a circular buffer
// in m_deleted_rows_window vector
@@ -104,37 +95,28 @@ void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type)
rocksdb_compaction_sequential_deletes_count_sd));
// Only make changes if the value at the current position needs to change
if (is_delete != m_deleted_rows_window[m_window_pos])
{
if (is_delete != m_deleted_rows_window[m_window_pos]) {
// Set or clear the flag at the current position as appropriate
m_deleted_rows_window[m_window_pos] = is_delete;
if (!is_delete)
{
if (!is_delete) {
m_deleted_rows--;
}
else if (++m_deleted_rows > m_max_deleted_rows)
{
} else if (++m_deleted_rows > m_max_deleted_rows) {
m_max_deleted_rows = m_deleted_rows;
}
}
if (++m_window_pos == m_params.m_window)
{
if (++m_window_pos == m_params.m_window) {
m_window_pos = 0;
}
}
}
Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
const rocksdb::Slice& key)
{
GL_INDEX_ID gl_index_id = {
.cf_id = m_cf_id,
.index_id = rdb_netbuf_to_uint32(reinterpret_cast<const uchar*>(key.data()))
};
Rdb_index_stats *Rdb_tbl_prop_coll::AccessStats(const rocksdb::Slice &key) {
GL_INDEX_ID gl_index_id = {.cf_id = m_cf_id,
.index_id = rdb_netbuf_to_uint32(
reinterpret_cast<const uchar *>(key.data()))};
if (m_last_stats == nullptr || m_last_stats->m_gl_index_id != gl_index_id)
{
if (m_last_stats == nullptr || m_last_stats->m_gl_index_id != gl_index_id) {
m_keydef = nullptr;
// starting a new table
@@ -142,8 +124,7 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
m_stats.emplace_back(gl_index_id);
m_last_stats = &m_stats.back();
if (m_ddl_manager)
{
if (m_ddl_manager) {
// safe_find() returns a std::shared_ptr<Rdb_key_def> with the count
// incremented (so it can't be deleted out from under us) and with
// the mutex locked (if setup has not occurred yet). We must make
@@ -152,8 +133,7 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
// when we are switching to a new Rdb_key_def and when this object
// is destructed.
m_keydef = m_ddl_manager->safe_find(gl_index_id);
if (m_keydef != nullptr)
{
if (m_keydef != nullptr) {
// resize the array to the number of columns.
// It will be initialized with zeroes
m_last_stats->m_distinct_keys_per_prefix.resize(
@@ -167,10 +147,10 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
return m_last_stats;
}
void Rdb_tbl_prop_coll::CollectStatsForRow(
const rocksdb::Slice& key, const rocksdb::Slice& value,
const rocksdb::EntryType &type, const uint64_t &file_size)
{
void Rdb_tbl_prop_coll::CollectStatsForRow(const rocksdb::Slice &key,
const rocksdb::Slice &value,
const rocksdb::EntryType &type,
const uint64_t &file_size) {
const auto stats = AccessStats(key);
stats->m_data_size += key.size() + value.size();
@@ -195,7 +175,8 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
default:
// NO_LINT_DEBUG
sql_print_error("RocksDB: Unexpected entry type found: %u. "
"This should not happen so aborting the system.", type);
"This should not happen so aborting the system.",
type);
abort_with_stack_traces();
break;
}
@@ -203,23 +184,19 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
stats->m_actual_disk_size += file_size - m_file_size;
m_file_size = file_size;
if (m_keydef != nullptr && ShouldCollectStats())
{
if (m_keydef != nullptr && ShouldCollectStats()) {
std::size_t column = 0;
bool new_key = true;
if (!m_last_key.empty())
{
if (!m_last_key.empty()) {
rocksdb::Slice last(m_last_key.data(), m_last_key.size());
new_key = (m_keydef->compare_keys(&last, &key, &column) == 0);
}
if (new_key)
{
if (new_key) {
DBUG_ASSERT(column <= stats->m_distinct_keys_per_prefix.size());
for (auto i = column; i < stats->m_distinct_keys_per_prefix.size(); i++)
{
for (auto i = column; i < stats->m_distinct_keys_per_prefix.size(); i++) {
stats->m_distinct_keys_per_prefix[i]++;
}
@@ -228,8 +205,7 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
// if one of the first n-1 columns is different
// If the n-1 prefix is the same, no sense in storing
// the new key
if (column < stats->m_distinct_keys_per_prefix.size())
{
if (column < stats->m_distinct_keys_per_prefix.size()) {
m_last_key.assign(key.data(), key.size());
}
}
@@ -242,9 +218,7 @@ const char* Rdb_tbl_prop_coll::INDEXSTATS_KEY = "__indexstats__";
This function is called by RocksDB to compute properties to store in sst file
*/
rocksdb::Status
Rdb_tbl_prop_coll::Finish(
rocksdb::UserCollectedProperties* const properties
) {
Rdb_tbl_prop_coll::Finish(rocksdb::UserCollectedProperties *const properties) {
uint64_t num_sst_entry_put = 0;
uint64_t num_sst_entry_delete = 0;
uint64_t num_sst_entry_singledelete = 0;
@@ -253,8 +227,7 @@ Rdb_tbl_prop_coll::Finish(
DBUG_ASSERT(properties != nullptr);
for (auto it = m_stats.begin(); it != m_stats.end(); it++)
{
for (auto it = m_stats.begin(); it != m_stats.end(); it++) {
num_sst_entry_put += it->m_rows;
num_sst_entry_delete += it->m_entry_deletes;
num_sst_entry_singledelete += it->m_entry_single_deletes;
@@ -262,28 +235,23 @@ Rdb_tbl_prop_coll::Finish(
num_sst_entry_other += it->m_entry_others;
}
if (num_sst_entry_put > 0)
{
if (num_sst_entry_put > 0) {
rocksdb_num_sst_entry_put += num_sst_entry_put;
}
if (num_sst_entry_delete > 0)
{
if (num_sst_entry_delete > 0) {
rocksdb_num_sst_entry_delete += num_sst_entry_delete;
}
if (num_sst_entry_singledelete > 0)
{
if (num_sst_entry_singledelete > 0) {
rocksdb_num_sst_entry_singledelete += num_sst_entry_singledelete;
}
if (num_sst_entry_merge > 0)
{
if (num_sst_entry_merge > 0) {
rocksdb_num_sst_entry_merge += num_sst_entry_merge;
}
if (num_sst_entry_other > 0)
{
if (num_sst_entry_other > 0) {
rocksdb_num_sst_entry_other += num_sst_entry_other;
}
@@ -293,9 +261,7 @@ Rdb_tbl_prop_coll::Finish(
}
bool Rdb_tbl_prop_coll::NeedCompact() const {
return
m_params.m_deletes &&
(m_params.m_window > 0) &&
return m_params.m_deletes && (m_params.m_window > 0) &&
(m_file_size > m_params.m_file_size) &&
(m_max_deleted_rows > m_params.m_deletes);
}
@@ -307,8 +273,8 @@ bool Rdb_tbl_prop_coll::ShouldCollectStats() {
return true;
}
const int val = rand_r(&m_seed) %
(RDB_TBL_STATS_SAMPLE_PCT_MAX - RDB_TBL_STATS_SAMPLE_PCT_MIN + 1) +
const int val = rand_r(&m_seed) % (RDB_TBL_STATS_SAMPLE_PCT_MAX -
RDB_TBL_STATS_SAMPLE_PCT_MIN + 1) +
RDB_TBL_STATS_SAMPLE_PCT_MIN;
DBUG_ASSERT(val >= RDB_TBL_STATS_SAMPLE_PCT_MIN);
@@ -341,10 +307,7 @@ Rdb_tbl_prop_coll::GetReadableProperties() const {
return rocksdb::UserCollectedProperties{{INDEXSTATS_KEY, s}};
}
std::string
Rdb_tbl_prop_coll::GetReadableStats(
const Rdb_index_stats& it
) {
std::string Rdb_tbl_prop_coll::GetReadableStats(const Rdb_index_stats &it) {
std::string s;
s.append("(");
s.append(std::to_string(it.m_gl_index_id.cf_id));
@@ -381,27 +344,23 @@ Rdb_tbl_prop_coll::GetReadableStats(
void Rdb_tbl_prop_coll::read_stats_from_tbl_props(
const std::shared_ptr<const rocksdb::TableProperties> &table_props,
std::vector<Rdb_index_stats>* const out_stats_vector)
{
std::vector<Rdb_index_stats> *const out_stats_vector) {
DBUG_ASSERT(out_stats_vector != nullptr);
const auto &user_properties = table_props->user_collected_properties;
const auto it2 = user_properties.find(std::string(INDEXSTATS_KEY));
if (it2 != user_properties.end())
{
auto result __attribute__((__unused__)) =
if (it2 != user_properties.end()) {
auto result MY_ATTRIBUTE((__unused__)) =
Rdb_index_stats::unmaterialize(it2->second, out_stats_vector);
DBUG_ASSERT(result == 0);
}
}
/*
Serializes an array of Rdb_index_stats into a network string.
*/
std::string Rdb_index_stats::materialize(
const std::vector<Rdb_index_stats>& stats,
const float card_adj_extra)
{
std::string
Rdb_index_stats::materialize(const std::vector<Rdb_index_stats> &stats,
const float card_adj_extra) {
String ret;
rdb_netstr_append_uint16(&ret, INDEX_STATS_VERSION_ENTRY_TYPES);
for (const auto &i : stats) {
@@ -428,99 +387,86 @@ std::string Rdb_index_stats::materialize(
/**
@brief
Reads an array of Rdb_index_stats from a string.
@return 1 if it detects any inconsistency in the input
@return 0 if completes successfully
@return HA_EXIT_FAILURE if it detects any inconsistency in the input
@return HA_EXIT_SUCCESS if completes successfully
*/
int Rdb_index_stats::unmaterialize(
const std::string& s, std::vector<Rdb_index_stats>* const ret)
{
int Rdb_index_stats::unmaterialize(const std::string &s,
std::vector<Rdb_index_stats> *const ret) {
const uchar *p = rdb_std_str_to_uchar_ptr(s);
const uchar *const p2 = p + s.size();
DBUG_ASSERT(ret != nullptr);
if (p+2 > p2)
{
return 1;
if (p + 2 > p2) {
return HA_EXIT_FAILURE;
}
const int version = rdb_netbuf_read_uint16(&p);
Rdb_index_stats stats;
// Make sure version is within supported range.
if (version < INDEX_STATS_VERSION_INITIAL ||
version > INDEX_STATS_VERSION_ENTRY_TYPES)
{
version > INDEX_STATS_VERSION_ENTRY_TYPES) {
// NO_LINT_DEBUG
sql_print_error("Index stats version %d was outside of supported range. "
"This should not happen so aborting the system.", version);
"This should not happen so aborting the system.",
version);
abort_with_stack_traces();
}
size_t needed = sizeof(stats.m_gl_index_id.cf_id) +
sizeof(stats.m_gl_index_id.index_id) +
sizeof(stats.m_data_size)+
sizeof(stats.m_rows)+
sizeof(stats.m_actual_disk_size)+
sizeof(uint64);
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES)
{
sizeof(stats.m_data_size) + sizeof(stats.m_rows) +
sizeof(stats.m_actual_disk_size) + sizeof(uint64);
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES) {
needed += sizeof(stats.m_entry_deletes) +
sizeof(stats.m_entry_single_deletes) +
sizeof(stats.m_entry_merges)+
sizeof(stats.m_entry_others);
sizeof(stats.m_entry_merges) + sizeof(stats.m_entry_others);
}
while (p < p2)
{
if (p+needed > p2)
{
return 1;
while (p < p2) {
if (p + needed > p2) {
return HA_EXIT_FAILURE;
}
rdb_netbuf_read_gl_index(&p, &stats.m_gl_index_id);
stats.m_data_size = rdb_netbuf_read_uint64(&p);
stats.m_rows = rdb_netbuf_read_uint64(&p);
stats.m_actual_disk_size = rdb_netbuf_read_uint64(&p);
stats.m_distinct_keys_per_prefix.resize(rdb_netbuf_read_uint64(&p));
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES)
{
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES) {
stats.m_entry_deletes = rdb_netbuf_read_uint64(&p);
stats.m_entry_single_deletes = rdb_netbuf_read_uint64(&p);
stats.m_entry_merges = rdb_netbuf_read_uint64(&p);
stats.m_entry_others = rdb_netbuf_read_uint64(&p);
}
if (p+stats.m_distinct_keys_per_prefix.size()
*sizeof(stats.m_distinct_keys_per_prefix[0]) > p2)
{
return 1;
if (p +
stats.m_distinct_keys_per_prefix.size() *
sizeof(stats.m_distinct_keys_per_prefix[0]) >
p2) {
return HA_EXIT_FAILURE;
}
for (std::size_t i= 0; i < stats.m_distinct_keys_per_prefix.size(); i++)
{
for (std::size_t i = 0; i < stats.m_distinct_keys_per_prefix.size(); i++) {
stats.m_distinct_keys_per_prefix[i] = rdb_netbuf_read_uint64(&p);
}
ret->push_back(stats);
}
return 0;
return HA_EXIT_SUCCESS;
}
/*
Merges one Rdb_index_stats into another. Can be used to come up with the stats
for the index based on stats for each sst
*/
void Rdb_index_stats::merge(
const Rdb_index_stats& s, const bool &increment,
const int64_t &estimated_data_len)
{
void Rdb_index_stats::merge(const Rdb_index_stats &s, const bool &increment,
const int64_t &estimated_data_len) {
std::size_t i;
DBUG_ASSERT(estimated_data_len >= 0);
m_gl_index_id = s.m_gl_index_id;
if (m_distinct_keys_per_prefix.size() < s.m_distinct_keys_per_prefix.size())
{
if (m_distinct_keys_per_prefix.size() < s.m_distinct_keys_per_prefix.size()) {
m_distinct_keys_per_prefix.resize(s.m_distinct_keys_per_prefix.size());
}
if (increment)
{
if (increment) {
m_rows += s.m_rows;
m_data_size += s.m_data_size;
@@ -531,29 +477,25 @@ void Rdb_index_stats::merge(
we make a reasoned estimate for the data_file_length for the
index in the current SST.
*/
m_actual_disk_size += s.m_actual_disk_size ? s.m_actual_disk_size :
estimated_data_len * s.m_rows;
m_actual_disk_size += s.m_actual_disk_size ? s.m_actual_disk_size
: estimated_data_len * s.m_rows;
m_entry_deletes += s.m_entry_deletes;
m_entry_single_deletes += s.m_entry_single_deletes;
m_entry_merges += s.m_entry_merges;
m_entry_others += s.m_entry_others;
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++)
{
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++) {
m_distinct_keys_per_prefix[i] += s.m_distinct_keys_per_prefix[i];
}
}
else
{
} else {
m_rows -= s.m_rows;
m_data_size -= s.m_data_size;
m_actual_disk_size -= s.m_actual_disk_size ? s.m_actual_disk_size :
estimated_data_len * s.m_rows;
m_actual_disk_size -= s.m_actual_disk_size ? s.m_actual_disk_size
: estimated_data_len * s.m_rows;
m_entry_deletes -= s.m_entry_deletes;
m_entry_single_deletes -= s.m_entry_single_deletes;
m_entry_merges -= s.m_entry_merges;
m_entry_others -= s.m_entry_others;
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++)
{
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++) {
m_distinct_keys_per_prefix[i] -= s.m_distinct_keys_per_prefix[i];
}
}

View File

@@ -40,15 +40,11 @@ extern std::atomic<uint64_t> rocksdb_num_sst_entry_merge;
extern std::atomic<uint64_t> rocksdb_num_sst_entry_other;
extern my_bool rocksdb_compaction_sequential_deletes_count_sd;
struct Rdb_compact_params
{
struct Rdb_compact_params {
uint64_t m_deletes, m_window, m_file_size;
};
struct Rdb_index_stats
{
struct Rdb_index_stats {
enum {
INDEX_STATS_VERSION_INITIAL = 1,
INDEX_STATS_VERSION_ENTRY_TYPES = 2,
@@ -66,54 +62,42 @@ struct Rdb_index_stats
std::vector<Rdb_index_stats> *const ret);
Rdb_index_stats() : Rdb_index_stats({0, 0}) {}
explicit Rdb_index_stats(GL_INDEX_ID gl_index_id) :
m_gl_index_id(gl_index_id),
m_data_size(0),
m_rows(0),
m_actual_disk_size(0),
m_entry_deletes(0),
m_entry_single_deletes(0),
m_entry_merges(0),
m_entry_others(0) {}
explicit Rdb_index_stats(GL_INDEX_ID gl_index_id)
: m_gl_index_id(gl_index_id), m_data_size(0), m_rows(0),
m_actual_disk_size(0), m_entry_deletes(0), m_entry_single_deletes(0),
m_entry_merges(0), m_entry_others(0) {}
void merge(const Rdb_index_stats &s, const bool &increment = true,
const int64_t &estimated_data_len = 0);
};
class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
{
class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector {
public:
Rdb_tbl_prop_coll(
Rdb_ddl_manager* const ddl_manager,
const Rdb_compact_params &params,
const uint32_t &cf_id,
const uint8_t &table_stats_sampling_pct
);
Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
const Rdb_compact_params &params, const uint32_t &cf_id,
const uint8_t &table_stats_sampling_pct);
/*
Override parent class's virtual methods of interest.
*/
virtual rocksdb::Status AddUserKey(
const rocksdb::Slice& key, const rocksdb::Slice& value,
rocksdb::EntryType type, rocksdb::SequenceNumber seq,
virtual rocksdb::Status AddUserKey(const rocksdb::Slice &key,
const rocksdb::Slice &value,
rocksdb::EntryType type,
rocksdb::SequenceNumber seq,
uint64_t file_size);
virtual rocksdb::Status Finish(rocksdb::UserCollectedProperties* properties) override;
virtual rocksdb::Status
Finish(rocksdb::UserCollectedProperties *properties) override;
virtual const char* Name() const override {
return "Rdb_tbl_prop_coll";
}
virtual const char *Name() const override { return "Rdb_tbl_prop_coll"; }
rocksdb::UserCollectedProperties GetReadableProperties() const override;
bool NeedCompact() const override;
public:
uint64_t GetMaxDeletedRows() const {
return m_max_deleted_rows;
}
uint64_t GetMaxDeletedRows() const { return m_max_deleted_rows; }
static void read_stats_from_tbl_props(
const std::shared_ptr<const rocksdb::TableProperties> &table_props,
@@ -124,7 +108,8 @@ class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
bool ShouldCollectStats();
void CollectStatsForRow(const rocksdb::Slice &key,
const rocksdb::Slice& value, const rocksdb::EntryType &type,
const rocksdb::Slice &value,
const rocksdb::EntryType &type,
const uint64_t &file_size);
Rdb_index_stats *AccessStats(const rocksdb::Slice &key);
void AdjustDeletedRows(rocksdb::EntryType type);
@@ -150,16 +135,15 @@ class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
float m_card_adj_extra;
};
class Rdb_tbl_prop_coll_factory
: public rocksdb::TablePropertiesCollectorFactory {
public:
Rdb_tbl_prop_coll_factory(const Rdb_tbl_prop_coll_factory &) = delete;
Rdb_tbl_prop_coll_factory& operator=(const Rdb_tbl_prop_coll_factory&) = delete;
Rdb_tbl_prop_coll_factory &
operator=(const Rdb_tbl_prop_coll_factory &) = delete;
explicit Rdb_tbl_prop_coll_factory(Rdb_ddl_manager *ddl_manager)
: m_ddl_manager(ddl_manager) {
}
: m_ddl_manager(ddl_manager) {}
/*
Override parent class's virtual methods of interest.
@@ -167,8 +151,8 @@ class Rdb_tbl_prop_coll_factory
virtual rocksdb::TablePropertiesCollector *CreateTablePropertiesCollector(
rocksdb::TablePropertiesCollectorFactory::Context context) override {
return new Rdb_tbl_prop_coll(
m_ddl_manager, m_params, context.column_family_id,
return new Rdb_tbl_prop_coll(m_ddl_manager, m_params,
context.column_family_id,
m_table_stats_sampling_pct);
}

View File

@@ -28,8 +28,7 @@ namespace myrocks {
*/
inline void rdb_netstr_append_uint64(my_core::String *const out_netstr,
const uint64 &val)
{
const uint64 &val) {
DBUG_ASSERT(out_netstr != nullptr);
// Convert from host machine byte order (usually Little Endian) to network
@@ -39,8 +38,7 @@ inline void rdb_netstr_append_uint64(my_core::String* const out_netstr,
}
inline void rdb_netstr_append_uint32(my_core::String *const out_netstr,
const uint32 &val)
{
const uint32 &val) {
DBUG_ASSERT(out_netstr != nullptr);
// Convert from host machine byte order (usually Little Endian) to network
@@ -50,8 +48,7 @@ inline void rdb_netstr_append_uint32(my_core::String* const out_netstr,
}
inline void rdb_netstr_append_uint16(my_core::String *const out_netstr,
const uint16 &val)
{
const uint16 &val) {
DBUG_ASSERT(out_netstr != nullptr);
// Convert from host machine byte order (usually Little Endian) to network
@@ -60,13 +57,11 @@ inline void rdb_netstr_append_uint16(my_core::String* const out_netstr,
out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
}
/*
Basic network buffer ("netbuf") write helper functions.
*/
inline void rdb_netbuf_store_uint64(uchar* const dst_netbuf, const uint64 &n)
{
inline void rdb_netbuf_store_uint64(uchar *const dst_netbuf, const uint64 &n) {
DBUG_ASSERT(dst_netbuf != nullptr);
// Convert from host byte order (usually Little Endian) to network byte order
@@ -75,8 +70,7 @@ inline void rdb_netbuf_store_uint64(uchar* const dst_netbuf, const uint64 &n)
memcpy(dst_netbuf, &net_val, sizeof(net_val));
}
inline void rdb_netbuf_store_uint32(uchar* const dst_netbuf, const uint32 &n)
{
inline void rdb_netbuf_store_uint32(uchar *const dst_netbuf, const uint32 &n) {
DBUG_ASSERT(dst_netbuf != nullptr);
// Convert from host byte order (usually Little Endian) to network byte order
@@ -85,8 +79,7 @@ inline void rdb_netbuf_store_uint32(uchar* const dst_netbuf, const uint32 &n)
memcpy(dst_netbuf, &net_val, sizeof(net_val));
}
inline void rdb_netbuf_store_uint16(uchar* const dst_netbuf, const uint16 &n)
{
inline void rdb_netbuf_store_uint16(uchar *const dst_netbuf, const uint16 &n) {
DBUG_ASSERT(dst_netbuf != nullptr);
// Convert from host byte order (usually Little Endian) to network byte order
@@ -95,29 +88,25 @@ inline void rdb_netbuf_store_uint16(uchar* const dst_netbuf, const uint16 &n)
memcpy(dst_netbuf, &net_val, sizeof(net_val));
}
inline void rdb_netbuf_store_byte(uchar* const dst_netbuf, const uchar &c)
{
inline void rdb_netbuf_store_byte(uchar *const dst_netbuf, const uchar &c) {
DBUG_ASSERT(dst_netbuf != nullptr);
*dst_netbuf = c;
}
inline void rdb_netbuf_store_index(uchar *const dst_netbuf,
const uint32 &number)
{
const uint32 &number) {
DBUG_ASSERT(dst_netbuf != nullptr);
rdb_netbuf_store_uint32(dst_netbuf, number);
}
/*
Basic conversion helper functions from network byte order (Big Endian) to host
machine byte order (usually Little Endian).
*/
inline uint64 rdb_netbuf_to_uint64(const uchar* const netbuf)
{
inline uint64 rdb_netbuf_to_uint64(const uchar *const netbuf) {
DBUG_ASSERT(netbuf != nullptr);
uint64 net_val;
@@ -128,8 +117,7 @@ inline uint64 rdb_netbuf_to_uint64(const uchar* const netbuf)
return be64toh(net_val);
}
inline uint32 rdb_netbuf_to_uint32(const uchar* const netbuf)
{
inline uint32 rdb_netbuf_to_uint32(const uchar *const netbuf) {
DBUG_ASSERT(netbuf != nullptr);
uint32 net_val;
@@ -140,8 +128,7 @@ inline uint32 rdb_netbuf_to_uint32(const uchar* const netbuf)
return be32toh(net_val);
}
inline uint16 rdb_netbuf_to_uint16(const uchar* const netbuf)
{
inline uint16 rdb_netbuf_to_uint16(const uchar *const netbuf) {
DBUG_ASSERT(netbuf != nullptr);
uint16 net_val;
@@ -152,14 +139,12 @@ inline uint16 rdb_netbuf_to_uint16(const uchar* const netbuf)
return be16toh(net_val);
}
inline uchar rdb_netbuf_to_byte(const uchar* const netbuf)
{
inline uchar rdb_netbuf_to_byte(const uchar *const netbuf) {
DBUG_ASSERT(netbuf != nullptr);
return (uchar)netbuf[0];
}
/*
Basic network buffer ("netbuf") read helper functions.
Network buffer stores data in Network Byte Order (Big Endian).
@@ -167,8 +152,7 @@ inline uchar rdb_netbuf_to_byte(const uchar* const netbuf)
the netbuf pointer gets advanced to the following byte.
*/
inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr)
{
inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr) {
DBUG_ASSERT(netbuf_ptr != nullptr);
// Convert from network byte order (Big Endian) to host machine byte order
@@ -181,8 +165,7 @@ inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr)
return host_val;
}
inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr)
{
inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr) {
DBUG_ASSERT(netbuf_ptr != nullptr);
// Convert from network byte order (Big Endian) to host machine byte order
@@ -195,8 +178,7 @@ inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr)
return host_val;
}
inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr)
{
inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr) {
DBUG_ASSERT(netbuf_ptr != nullptr);
// Convert from network byte order (Big Endian) to host machine byte order
@@ -210,8 +192,7 @@ inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr)
}
inline void rdb_netbuf_read_gl_index(const uchar **netbuf_ptr,
GL_INDEX_ID* const gl_index_id)
{
GL_INDEX_ID *const gl_index_id) {
DBUG_ASSERT(gl_index_id != nullptr);
DBUG_ASSERT(netbuf_ptr != nullptr);
@@ -225,17 +206,17 @@ inline void rdb_netbuf_read_gl_index(const uchar **netbuf_ptr,
- it prevents one from reading beyond the end of the string.
*/
class Rdb_string_reader
{
class Rdb_string_reader {
const char *m_ptr;
uint m_len;
private:
Rdb_string_reader &operator=(const Rdb_string_reader &) = default;
public:
Rdb_string_reader(const Rdb_string_reader &) = default;
/* named constructor */
static Rdb_string_reader read_or_empty(const rocksdb::Slice* const slice)
{
static Rdb_string_reader read_or_empty(const rocksdb::Slice *const slice) {
if (!slice) {
return Rdb_string_reader("");
} else {
@@ -243,15 +224,11 @@ class Rdb_string_reader
}
}
explicit Rdb_string_reader(const std::string &str)
{
explicit Rdb_string_reader(const std::string &str) {
m_len = str.length();
if (m_len)
{
if (m_len) {
m_ptr = &str.at(0);
}
else
{
} else {
/*
One can a create a Rdb_string_reader for reading from an empty string
(although attempts to read anything will fail).
@@ -262,8 +239,7 @@ class Rdb_string_reader
}
}
explicit Rdb_string_reader(const rocksdb::Slice* const slice)
{
explicit Rdb_string_reader(const rocksdb::Slice *const slice) {
m_ptr = slice->data();
m_len = slice->size();
}
@@ -272,15 +248,11 @@ class Rdb_string_reader
Read the next @param size bytes. Returns pointer to the bytes read, or
nullptr if the remaining string doesn't have that many bytes.
*/
const char *read(const uint &size)
{
const char *read(const uint &size) {
const char *res;
if (m_len < size)
{
if (m_len < size) {
res = nullptr;
}
else
{
} else {
res = m_ptr;
m_ptr += size;
m_len -= size;
@@ -288,25 +260,21 @@ class Rdb_string_reader
return res;
}
bool read_uint8(uint* const res)
{
bool read_uint8(uint *const res) {
const uchar *p;
if (!(p = reinterpret_cast<const uchar *>(read(1))))
return true; // error
else
{
else {
*res = *p;
return false; // Ok
}
}
bool read_uint16(uint* const res)
{
bool read_uint16(uint *const res) {
const uchar *p;
if (!(p = reinterpret_cast<const uchar *>(read(2))))
return true; // error
else
{
else {
*res = rdb_netbuf_to_uint16(p);
return false; // Ok
}
@@ -322,7 +290,6 @@ class Rdb_string_reader
const char *get_current_ptr() const { return m_ptr; }
};
/*
@brief
A buffer one can write the data to.
@@ -338,36 +305,32 @@ class Rdb_string_reader
*/
class Rdb_string_writer
{
class Rdb_string_writer {
std::vector<uchar> m_data;
public:
Rdb_string_writer(const Rdb_string_writer &) = delete;
Rdb_string_writer &operator=(const Rdb_string_writer &) = delete;
Rdb_string_writer() = default;
void clear() { m_data.clear(); }
void write_uint8(const uint &val)
{
void write_uint8(const uint &val) {
m_data.push_back(static_cast<uchar>(val));
}
void write_uint16(const uint &val)
{
void write_uint16(const uint &val) {
const auto size = m_data.size();
m_data.resize(size + 2);
rdb_netbuf_store_uint16(m_data.data() + size, val);
}
void write_uint32(const uint &val)
{
void write_uint32(const uint &val) {
const auto size = m_data.size();
m_data.resize(size + 4);
rdb_netbuf_store_uint32(m_data.data() + size, val);
}
void write(const uchar* const new_data, const size_t &len)
{
void write(const uchar *const new_data, const size_t &len) {
DBUG_ASSERT(new_data != nullptr);
m_data.insert(m_data.end(), new_data, new_data + len);
}
@@ -375,95 +338,79 @@ class Rdb_string_writer
uchar *ptr() { return m_data.data(); }
size_t get_current_pos() const { return m_data.size(); }
void write_uint8_at(const size_t &pos, const uint &new_val)
{
void write_uint8_at(const size_t &pos, const uint &new_val) {
// This function will only overwrite what was written
DBUG_ASSERT(pos < get_current_pos());
m_data.data()[pos] = new_val;
}
void write_uint16_at(const size_t &pos, const uint &new_val)
{
void write_uint16_at(const size_t &pos, const uint &new_val) {
// This function will only overwrite what was written
DBUG_ASSERT(pos < get_current_pos() && (pos + 1) < get_current_pos());
rdb_netbuf_store_uint16(m_data.data() + pos, new_val);
}
};
/*
A helper class for writing bits into Rdb_string_writer.
The class assumes (but doesn't check) that nobody tries to write
anything to the Rdb_string_writer that it is writing to.
*/
class Rdb_bit_writer
{
class Rdb_bit_writer {
Rdb_string_writer *m_writer;
uchar m_offset;
public:
Rdb_bit_writer(const Rdb_bit_writer &) = delete;
Rdb_bit_writer &operator=(const Rdb_bit_writer &) = delete;
explicit Rdb_bit_writer(Rdb_string_writer *writer_arg)
: m_writer(writer_arg),
m_offset(0)
{
}
: m_writer(writer_arg), m_offset(0) {}
void write(uint size, const uint &value)
{
void write(uint size, const uint &value) {
DBUG_ASSERT((value & ((1 << size) - 1)) == value);
while (size > 0)
{
if (m_offset == 0)
{
while (size > 0) {
if (m_offset == 0) {
m_writer->write_uint8(0);
}
// number of bits to put in this byte
const uint bits = std::min(size, (uint)(8 - m_offset));
uchar* const last_byte= m_writer->ptr() + m_writer->get_current_pos() - 1;
*last_byte |=
(uchar) ((value >> (size - bits)) & ((1 << bits) - 1)) << m_offset;
uchar *const last_byte =
m_writer->ptr() + m_writer->get_current_pos() - 1;
*last_byte |= (uchar)((value >> (size - bits)) & ((1 << bits) - 1))
<< m_offset;
size -= bits;
m_offset = (m_offset + bits) & 0x7;
}
}
};
class Rdb_bit_reader
{
class Rdb_bit_reader {
const uchar *m_cur;
uchar m_offset;
uint m_ret;
Rdb_string_reader *const m_reader;
public:
Rdb_bit_reader(const Rdb_bit_reader &) = delete;
Rdb_bit_reader &operator=(const Rdb_bit_reader &) = delete;
explicit Rdb_bit_reader(Rdb_string_reader *const reader)
: m_cur(nullptr),
m_offset(0),
m_reader(reader)
{
}
: m_cur(nullptr), m_offset(0), m_reader(reader) {}
// Returns a pointer to an uint containing the bits read. On subsequent
// reads, the value being pointed to will be overwritten. Returns nullptr
// on failure.
uint *read(uint size)
{
uint *read(uint size) {
m_ret = 0;
DBUG_ASSERT(size <= 32);
while (size > 0)
{
if (m_offset == 0)
{
while (size > 0) {
if (m_offset == 0) {
m_cur = (const uchar *)m_reader->read(1);
if (m_cur == nullptr)
{
if (m_cur == nullptr) {
return nullptr;
}
}

View File

@@ -28,8 +28,7 @@
namespace myrocks {
/* Check if ColumnFamily name says it's a reverse-ordered CF */
bool Rdb_cf_manager::is_cf_name_reverse(const char* const name)
{
bool Rdb_cf_manager::is_cf_name_reverse(const char *const name) {
/* nullptr means the default CF is used.. (TODO: can the default CF be
* reverse?) */
if (name && !strncmp(name, "rev:", 4))
@@ -44,8 +43,7 @@ static PSI_mutex_key ex_key_cfm;
void Rdb_cf_manager::init(
Rdb_cf_options *const cf_options,
std::vector<rocksdb::ColumnFamilyHandle*>* const handles)
{
std::vector<rocksdb::ColumnFamilyHandle *> *const handles) {
mysql_mutex_init(ex_key_cfm, &m_mutex, MY_MUTEX_INIT_FAST);
DBUG_ASSERT(cf_options != nullptr);
@@ -61,16 +59,13 @@ void Rdb_cf_manager::init(
}
}
void Rdb_cf_manager::cleanup()
{
void Rdb_cf_manager::cleanup() {
for (auto it : m_cf_name_map) {
delete it.second;
}
mysql_mutex_destroy(&m_mutex);
}
/**
Generate Column Family name for per-index column families
@@ -79,15 +74,13 @@ void Rdb_cf_manager::cleanup()
void Rdb_cf_manager::get_per_index_cf_name(const std::string &db_table_name,
const char *const index_name,
std::string* const res)
{
std::string *const res) {
DBUG_ASSERT(index_name != nullptr);
DBUG_ASSERT(res != nullptr);
*res = db_table_name + "." + index_name;
}
/*
@brief
Find column family by name. If it doesn't exist, create it
@@ -96,12 +89,10 @@ void Rdb_cf_manager::get_per_index_cf_name(const std::string& db_table_name,
See Rdb_cf_manager::get_cf
*/
rocksdb::ColumnFamilyHandle *
Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
const char *cf_name,
Rdb_cf_manager::get_or_create_cf(rocksdb::DB *const rdb, const char *cf_name,
const std::string &db_table_name,
const char *const index_name,
bool* const is_automatic)
{
bool *const is_automatic) {
DBUG_ASSERT(rdb != nullptr);
DBUG_ASSERT(is_automatic != nullptr);
@@ -113,8 +104,7 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
cf_name = DEFAULT_CF_NAME;
std::string per_index_name;
if (!strcmp(cf_name, PER_INDEX_CF_NAME))
{
if (!strcmp(cf_name, PER_INDEX_CF_NAME)) {
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
cf_name = per_index_name.c_str();
*is_automatic = true;
@@ -123,14 +113,14 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
const auto it = m_cf_name_map.find(cf_name);
if (it != m_cf_name_map.end())
cf_handle = it->second;
else
{
else {
/* Create a Column Family. */
const std::string cf_name_str(cf_name);
rocksdb::ColumnFamilyOptions opts;
m_cf_options->get_cf_options(cf_name_str, &opts);
sql_print_information("RocksDB: creating column family %s", cf_name_str.c_str());
sql_print_information("RocksDB: creating column family %s",
cf_name_str.c_str());
sql_print_information(" write_buffer_size=%ld", opts.write_buffer_size);
sql_print_information(" target_file_size_base=%" PRIu64,
opts.target_file_size_base);
@@ -149,7 +139,6 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
return cf_handle;
}
/*
Find column family by its cf_name.
@@ -163,11 +152,9 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
*/
rocksdb::ColumnFamilyHandle *
Rdb_cf_manager::get_cf(const char *cf_name,
const std::string& db_table_name,
Rdb_cf_manager::get_cf(const char *cf_name, const std::string &db_table_name,
const char *const index_name,
bool* const is_automatic) const
{
bool *const is_automatic) const {
DBUG_ASSERT(is_automatic != nullptr);
rocksdb::ColumnFamilyHandle *cf_handle;
@@ -178,8 +165,7 @@ Rdb_cf_manager::get_cf(const char *cf_name,
cf_name = DEFAULT_CF_NAME;
std::string per_index_name;
if (!strcmp(cf_name, PER_INDEX_CF_NAME))
{
if (!strcmp(cf_name, PER_INDEX_CF_NAME)) {
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
cf_name = per_index_name.c_str();
*is_automatic = true;
@@ -193,8 +179,7 @@ Rdb_cf_manager::get_cf(const char *cf_name,
return cf_handle;
}
rocksdb::ColumnFamilyHandle* Rdb_cf_manager::get_cf(const uint32_t &id) const
{
rocksdb::ColumnFamilyHandle *Rdb_cf_manager::get_cf(const uint32_t &id) const {
rocksdb::ColumnFamilyHandle *cf_handle = nullptr;
mysql_mutex_lock(&m_mutex);
@@ -206,9 +191,7 @@ rocksdb::ColumnFamilyHandle* Rdb_cf_manager::get_cf(const uint32_t &id) const
return cf_handle;
}
std::vector<std::string>
Rdb_cf_manager::get_cf_names(void) const
{
std::vector<std::string> Rdb_cf_manager::get_cf_names(void) const {
std::vector<std::string> names;
mysql_mutex_lock(&m_mutex);
@@ -220,8 +203,7 @@ Rdb_cf_manager::get_cf_names(void) const
}
std::vector<rocksdb::ColumnFamilyHandle *>
Rdb_cf_manager::get_all_cf(void) const
{
Rdb_cf_manager::get_all_cf(void) const {
std::vector<rocksdb::ColumnFamilyHandle *> list;
mysql_mutex_lock(&m_mutex);

View File

@@ -46,15 +46,13 @@ namespace myrocks {
- CFs are created in a synchronized way. We can't remove them, yet.
*/
class Rdb_cf_manager
{
class Rdb_cf_manager {
std::map<std::string, rocksdb::ColumnFamilyHandle *> m_cf_name_map;
std::map<uint32_t, rocksdb::ColumnFamilyHandle *> m_cf_id_map;
mutable mysql_mutex_t m_mutex;
static
void get_per_index_cf_name(const std::string& db_table_name,
static void get_per_index_cf_name(const std::string &db_table_name,
const char *const index_name,
std::string *const res);
@@ -68,7 +66,8 @@ public:
static bool is_cf_name_reverse(const char *const name);
/*
This is called right after the DB::Open() call. The parameters describe column
This is called right after the DB::Open() call. The parameters describe
column
families that are present in the database. The first CF is the default CF.
*/
void init(Rdb_cf_options *cf_options,
@@ -80,10 +79,10 @@ public:
- cf_name=nullptr means use default column family
- cf_name=_auto_ means use 'dbname.tablename.indexname'
*/
rocksdb::ColumnFamilyHandle* get_or_create_cf(
rocksdb::DB* const rdb, const char *cf_name,
const std::string& db_table_name, const char* const index_name,
bool* const is_automatic);
rocksdb::ColumnFamilyHandle *
get_or_create_cf(rocksdb::DB *const rdb, const char *cf_name,
const std::string &db_table_name,
const char *const index_name, bool *const is_automatic);
/* Used by table open */
rocksdb::ColumnFamilyHandle *get_cf(const char *cf_name,
@@ -102,9 +101,9 @@ public:
// void drop_cf(); -- not implemented so far.
void get_cf_options(
const std::string &cf_name,
rocksdb::ColumnFamilyOptions* const opts) __attribute__((__nonnull__)) {
void get_cf_options(const std::string &cf_name,
rocksdb::ColumnFamilyOptions *const opts)
MY_ATTRIBUTE((__nonnull__)) {
m_cf_options->get_cf_options(cf_name, opts);
}
};

View File

@@ -44,8 +44,7 @@ bool Rdb_cf_options::init(
const rocksdb::BlockBasedTableOptions &table_options,
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
const char *const default_cf_options,
const char* const override_cf_options)
{
const char *const override_cf_options) {
DBUG_ASSERT(default_cf_options != nullptr);
DBUG_ASSERT(override_cf_options != nullptr);
@@ -70,34 +69,27 @@ bool Rdb_cf_options::init(
}
void Rdb_cf_options::get(const std::string &cf_name,
rocksdb::ColumnFamilyOptions* const opts)
{
rocksdb::ColumnFamilyOptions *const opts) {
DBUG_ASSERT(opts != nullptr);
// set defaults
rocksdb::GetColumnFamilyOptionsFromString(*opts,
m_default_config,
opts);
rocksdb::GetColumnFamilyOptionsFromString(*opts, m_default_config, opts);
// set per-cf config if we have one
Name_to_config_t::iterator it = m_name_map.find(cf_name);
if (it != m_name_map.end()) {
rocksdb::GetColumnFamilyOptionsFromString(*opts,
it->second,
opts);
rocksdb::GetColumnFamilyOptionsFromString(*opts, it->second, opts);
}
}
bool Rdb_cf_options::set_default(const std::string &default_config)
{
bool Rdb_cf_options::set_default(const std::string &default_config) {
rocksdb::ColumnFamilyOptions options;
if (!default_config.empty() &&
!rocksdb::GetColumnFamilyOptionsFromString(options,
default_config,
&options).ok()) {
fprintf(stderr,
"Invalid default column family config: %s\n",
!rocksdb::GetColumnFamilyOptionsFromString(options, default_config,
&options)
.ok()) {
fprintf(stderr, "Invalid default column family config: %s\n",
default_config.c_str());
return false;
}
@@ -107,8 +99,7 @@ bool Rdb_cf_options::set_default(const std::string &default_config)
}
// Skip over any spaces in the input string.
void Rdb_cf_options::skip_spaces(const std::string& input, size_t* const pos)
{
void Rdb_cf_options::skip_spaces(const std::string &input, size_t *const pos) {
DBUG_ASSERT(pos != nullptr);
while (*pos < input.size() && isspace(input[*pos]))
@@ -120,8 +111,7 @@ void Rdb_cf_options::skip_spaces(const std::string& input, size_t* const pos)
// the beginning and end but are not removed between other characters.
bool Rdb_cf_options::find_column_family(const std::string &input,
size_t *const pos,
std::string* const key)
{
std::string *const key) {
DBUG_ASSERT(pos != nullptr);
DBUG_ASSERT(key != nullptr);
@@ -129,15 +119,13 @@ bool Rdb_cf_options::find_column_family(const std::string& input,
size_t end_pos = *pos - 1;
// Loop through the characters in the string until we see a '='.
for ( ; *pos < input.size() && input[*pos] != '='; ++(*pos))
{
for (; *pos < input.size() && input[*pos] != '='; ++(*pos)) {
// If this is not a space, move the end position to the current position.
if (input[*pos] != ' ')
end_pos = *pos;
}
if (end_pos == beg_pos - 1)
{
if (end_pos == beg_pos - 1) {
// NO_LINT_DEBUG
sql_print_warning("No column family found (options: %s)", input.c_str());
return false;
@@ -151,14 +139,12 @@ bool Rdb_cf_options::find_column_family(const std::string& input,
// portion until we hit as many close curly braces as we have seen open curly
// braces.
bool Rdb_cf_options::find_options(const std::string &input, size_t *const pos,
std::string* const options)
{
std::string *const options) {
DBUG_ASSERT(pos != nullptr);
DBUG_ASSERT(options != nullptr);
// Make sure we have an open curly brace at the current position.
if (*pos < input.size() && input[*pos] != '{')
{
if (*pos < input.size() && input[*pos] != '{') {
// NO_LINT_DEBUG
sql_print_warning("Invalid cf options, '{' expected (options: %s)",
input.c_str());
@@ -175,15 +161,12 @@ bool Rdb_cf_options::find_options(const std::string& input, size_t* const pos,
// Loop through the characters in the string until we find the appropriate
// number of closing curly braces.
while (*pos < input.size())
{
switch (input[*pos])
{
while (*pos < input.size()) {
switch (input[*pos]) {
case '}':
// If this is a closing curly brace and we bring the count down to zero
// we can exit the loop with a valid options string.
if (--brace_count == 0)
{
if (--brace_count == 0) {
*options = input.substr(beg_pos, *pos - beg_pos);
++(*pos); // Move past the last closing curly brace
return true;
@@ -215,8 +198,7 @@ bool Rdb_cf_options::find_options(const std::string& input, size_t* const pos,
bool Rdb_cf_options::find_cf_options_pair(const std::string &input,
size_t *const pos,
std::string *const cf,
std::string* const opt_str)
{
std::string *const opt_str) {
DBUG_ASSERT(pos != nullptr);
DBUG_ASSERT(cf != nullptr);
DBUG_ASSERT(opt_str != nullptr);
@@ -229,8 +211,7 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
return false;
// If we are at the end of the input then we generate an error.
if (*pos == input.size())
{
if (*pos == input.size()) {
// NO_LINT_DEBUG
sql_print_warning("Invalid cf options, '=' expected (options: %s)",
input.c_str());
@@ -250,10 +231,8 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
skip_spaces(input, pos);
// We should either be at the end of the input string or at a semicolon.
if (*pos < input.size())
{
if (input[*pos] != ';')
{
if (*pos < input.size()) {
if (input[*pos] != ';') {
// NO_LINT_DEBUG
sql_print_warning("Invalid cf options, ';' expected (options: %s)",
input.c_str());
@@ -266,8 +245,7 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
return true;
}
bool Rdb_cf_options::set_override(const std::string &override_config)
{
bool Rdb_cf_options::set_override(const std::string &override_config) {
// TODO(???): support updates?
std::string cf;
@@ -277,15 +255,13 @@ bool Rdb_cf_options::set_override(const std::string &override_config)
// Loop through the characters of the string until we reach the end.
size_t pos = 0;
while (pos < override_config.size())
{
while (pos < override_config.size()) {
// Attempt to find <cf>={<opt_str>}.
if (!find_cf_options_pair(override_config, &pos, &cf, &opt_str))
return false;
// Generate an error if we have already seen this column family.
if (configs.find(cf) != configs.end())
{
if (configs.find(cf) != configs.end()) {
// NO_LINT_DEBUG
sql_print_warning(
"Duplicate entry for %s in override options (options: %s)",
@@ -294,9 +270,8 @@ bool Rdb_cf_options::set_override(const std::string &override_config)
}
// Generate an error if the <opt_str> is not valid according to RocksDB.
if (!rocksdb::GetColumnFamilyOptionsFromString(
options, opt_str, &options).ok())
{
if (!rocksdb::GetColumnFamilyOptionsFromString(options, opt_str, &options)
.ok()) {
// NO_LINT_DEBUG
sql_print_warning(
"Invalid cf config for %s in override options (options: %s)",
@@ -314,22 +289,17 @@ bool Rdb_cf_options::set_override(const std::string &override_config)
return true;
}
const rocksdb::Comparator* Rdb_cf_options::get_cf_comparator(
const std::string& cf_name)
{
if (Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str()))
{
const rocksdb::Comparator *
Rdb_cf_options::get_cf_comparator(const std::string &cf_name) {
if (Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str())) {
return &s_rev_pk_comparator;
}
else
{
} else {
return &s_pk_comparator;
}
}
void Rdb_cf_options::get_cf_options(const std::string &cf_name,
rocksdb::ColumnFamilyOptions* const opts)
{
rocksdb::ColumnFamilyOptions *const opts) {
DBUG_ASSERT(opts != nullptr);
*opts = m_default_cf_opts;

View File

@@ -38,18 +38,18 @@ namespace myrocks {
and also there is a default value which applies to column
families not found in the map.
*/
class Rdb_cf_options
{
class Rdb_cf_options {
public:
Rdb_cf_options(const Rdb_cf_options &) = delete;
Rdb_cf_options &operator=(const Rdb_cf_options &) = delete;
Rdb_cf_options() = default;
void get(const std::string &cf_name, rocksdb::ColumnFamilyOptions* const opts);
void get(const std::string &cf_name,
rocksdb::ColumnFamilyOptions *const opts);
bool init(
const rocksdb::BlockBasedTableOptions& table_options,
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
bool init(const rocksdb::BlockBasedTableOptions &table_options,
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory>
prop_coll_factory,
const char *const default_cf_options,
const char *const override_cf_options);
@@ -57,12 +57,12 @@ class Rdb_cf_options
return m_default_cf_opts;
}
static const rocksdb::Comparator* get_cf_comparator(
const std::string& cf_name);
static const rocksdb::Comparator *
get_cf_comparator(const std::string &cf_name);
void get_cf_options(
const std::string &cf_name,
rocksdb::ColumnFamilyOptions* const opts) __attribute__((__nonnull__));
void get_cf_options(const std::string &cf_name,
rocksdb::ColumnFamilyOptions *const opts)
MY_ATTRIBUTE((__nonnull__));
private:
bool set_default(const std::string &default_config);

View File

@@ -32,8 +32,7 @@
namespace myrocks {
class Rdb_compact_filter : public rocksdb::CompactionFilter
{
class Rdb_compact_filter : public rocksdb::CompactionFilter {
public:
Rdb_compact_filter(const Rdb_compact_filter &) = delete;
Rdb_compact_filter &operator=(const Rdb_compact_filter &) = delete;
@@ -45,12 +44,10 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
// V1 Filter is thread safe on our usage (creating from Factory).
// Make sure to protect instance variables when switching to thread
// unsafe in the future.
virtual bool Filter(int level,
const rocksdb::Slice& key,
virtual bool Filter(int level, const rocksdb::Slice &key,
const rocksdb::Slice &existing_value,
std::string *new_value,
bool* value_changed) const override
{
bool *value_changed) const override {
DBUG_ASSERT(key.size() >= sizeof(uint32));
GL_INDEX_ID gl_index_id;
@@ -60,8 +57,7 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
if (gl_index_id != m_prev_index) // processing new index id
{
if (m_num_deleted > 0)
{
if (m_num_deleted > 0) {
m_num_deleted = 0;
}
m_should_delete =
@@ -69,8 +65,7 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
m_prev_index = gl_index_id;
}
if (m_should_delete)
{
if (m_should_delete) {
m_num_deleted++;
}
@@ -79,10 +74,7 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
virtual bool IgnoreSnapshots() const override { return true; }
virtual const char* Name() const override
{
return "Rdb_compact_filter";
}
virtual const char *Name() const override { return "Rdb_compact_filter"; }
private:
// Column family for this compaction filter
@@ -95,23 +87,19 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
mutable bool m_should_delete = false;
};
class Rdb_compact_filter_factory : public rocksdb::CompactionFilterFactory
{
class Rdb_compact_filter_factory : public rocksdb::CompactionFilterFactory {
public:
Rdb_compact_filter_factory(const Rdb_compact_filter_factory &) = delete;
Rdb_compact_filter_factory& operator=(const Rdb_compact_filter_factory&) = delete;
Rdb_compact_filter_factory &
operator=(const Rdb_compact_filter_factory &) = delete;
Rdb_compact_filter_factory() {}
~Rdb_compact_filter_factory() {}
const char* Name() const override
{
return "Rdb_compact_filter_factory";
}
const char *Name() const override { return "Rdb_compact_filter_factory"; }
std::unique_ptr<rocksdb::CompactionFilter> CreateCompactionFilter(
const rocksdb::CompactionFilter::Context& context) override
{
const rocksdb::CompactionFilter::Context &context) override {
return std::unique_ptr<rocksdb::CompactionFilter>(
new Rdb_compact_filter(context.column_family_id));
}

View File

@@ -24,6 +24,9 @@
/* RocksDB header files */
#include "rocksdb/comparator.h"
/* MyRocks header files */
#include "./rdb_utils.h"
namespace myrocks {
/*
@@ -32,15 +35,14 @@ namespace myrocks {
(todo: knowledge about this format is shared between this class and
Rdb_key_def)
*/
class Rdb_pk_comparator : public rocksdb::Comparator
{
class Rdb_pk_comparator : public rocksdb::Comparator {
public:
Rdb_pk_comparator(const Rdb_pk_comparator &) = delete;
Rdb_pk_comparator &operator=(const Rdb_pk_comparator &) = delete;
Rdb_pk_comparator() = default;
static int bytewise_compare(const rocksdb::Slice& a, const rocksdb::Slice& b)
{
static int bytewise_compare(const rocksdb::Slice &a,
const rocksdb::Slice &b) {
const size_t a_size = a.size();
const size_t b_size = b.size();
const size_t len = (a_size < b_size) ? a_size : b_size;
@@ -50,17 +52,15 @@ class Rdb_pk_comparator : public rocksdb::Comparator
return res;
/* Ok, res== 0 */
if (a_size != b_size)
{
if (a_size != b_size) {
return a_size < b_size ? -1 : 1;
}
return 0;
return HA_EXIT_SUCCESS;
}
/* Override virtual methods of interest */
int Compare(const rocksdb::Slice& a, const rocksdb::Slice& b) const override
{
int Compare(const rocksdb::Slice &a, const rocksdb::Slice &b) const override {
return bytewise_compare(a, b);
}
@@ -76,20 +76,18 @@ class Rdb_pk_comparator : public rocksdb::Comparator
void FindShortSuccessor(std::string *key) const override {}
};
class Rdb_rev_comparator : public rocksdb::Comparator
{
class Rdb_rev_comparator : public rocksdb::Comparator {
public:
Rdb_rev_comparator(const Rdb_rev_comparator &) = delete;
Rdb_rev_comparator &operator=(const Rdb_rev_comparator &) = delete;
Rdb_rev_comparator() = default;
static int bytewise_compare(const rocksdb::Slice& a, const rocksdb::Slice& b)
{
static int bytewise_compare(const rocksdb::Slice &a,
const rocksdb::Slice &b) {
return -Rdb_pk_comparator::bytewise_compare(a, b);
}
int Compare(const rocksdb::Slice& a, const rocksdb::Slice& b) const override
{
int Compare(const rocksdb::Slice &a, const rocksdb::Slice &b) const override {
return -Rdb_pk_comparator::bytewise_compare(a, b);
}
const char *Name() const override { return "rev:RocksDB_SE_v3.10"; }

File diff suppressed because it is too large Load Diff

View File

@@ -56,15 +56,13 @@ class Rdb_ddl_manager;
In order to accommodate both cases, we require both calls to be made and
unpack_info is passed as context data between the two.
*/
class Rdb_pack_field_context
{
class Rdb_pack_field_context {
public:
Rdb_pack_field_context(const Rdb_pack_field_context &) = delete;
Rdb_pack_field_context &operator=(const Rdb_pack_field_context &) = delete;
explicit Rdb_pack_field_context(Rdb_string_writer* const writer_arg) :
writer(writer_arg)
{}
explicit Rdb_pack_field_context(Rdb_string_writer *const writer_arg)
: writer(writer_arg) {}
// NULL means we're not producing unpack_info.
Rdb_string_writer *writer;
@@ -113,14 +111,13 @@ const char RDB_CHECKSUM_DATA_TAG= 0x01;
*/
const char RDB_UNPACK_DATA_TAG = 0x02;
const size_t RDB_UNPACK_DATA_LEN_SIZE = sizeof(uint16_t);
const size_t RDB_UNPACK_HEADER_SIZE= sizeof(RDB_UNPACK_DATA_TAG) +
RDB_UNPACK_DATA_LEN_SIZE;
const size_t RDB_UNPACK_HEADER_SIZE =
sizeof(RDB_UNPACK_DATA_TAG) + RDB_UNPACK_DATA_LEN_SIZE;
// Possible return values for rdb_index_field_unpack_t functions.
enum {
UNPACK_SUCCESS = 0,
UNPACK_FAILURE = 1,
UNPACK_INFO_MISSING= 2,
};
/*
@@ -163,19 +160,16 @@ enum {
reads.
*/
class Rdb_key_def
{
class Rdb_key_def {
public:
/* Convert a key from KeyTupleFormat to mem-comparable form */
uint pack_index_tuple(TABLE *const tbl, uchar *const pack_buffer,
uchar* const packed_tuple,
const uchar* const key_tuple,
uchar *const packed_tuple, const uchar *const key_tuple,
const key_part_map &keypart_map) const;
/* Convert a key from Table->record format to mem-comparable form */
uint pack_record(const TABLE *const tbl, uchar *const pack_buffer,
const uchar* const record,
uchar* const packed_tuple,
const uchar *const record, uchar *const packed_tuple,
Rdb_string_writer *const unpack_info,
const bool &should_store_row_debug_checksums,
const longlong &hidden_pk_id = 0, uint n_key_parts = 0,
@@ -186,8 +180,7 @@ public:
int unpack_record(TABLE *const table, uchar *const buf,
const rocksdb::Slice *const packed_key,
const rocksdb::Slice *const unpack_info,
const bool &verify_row_debug_checksums)
const;
const bool &verify_row_debug_checksums) const;
static bool unpack_info_has_checksum(const rocksdb::Slice &unpack_info);
int compare_keys(const rocksdb::Slice *key1, const rocksdb::Slice *key2,
@@ -196,15 +189,13 @@ public:
size_t key_length(const TABLE *const table, const rocksdb::Slice &key) const;
/* Get the key that is the "infimum" for this index */
inline void get_infimum_key(uchar* const key, uint* const size) const
{
inline void get_infimum_key(uchar *const key, uint *const size) const {
rdb_netbuf_store_index(key, m_index_number);
*size = INDEX_NUMBER_SIZE;
}
/* Get the key that is a "supremum" for this index */
inline void get_supremum_key(uchar* const key, uint* const size) const
{
inline void get_supremum_key(uchar *const key, uint *const size) const {
rdb_netbuf_store_index(key, m_index_number + 1);
*size = INDEX_NUMBER_SIZE;
}
@@ -217,8 +208,7 @@ public:
if X is a prefix of Y, then we consider that X = Y.
*/
// b describes the lookup key, which can be a prefix of a.
int cmp_full_keys(const rocksdb::Slice& a, const rocksdb::Slice& b) const
{
int cmp_full_keys(const rocksdb::Slice &a, const rocksdb::Slice &b) const {
DBUG_ASSERT(covers_key(a));
DBUG_ASSERT(covers_key(b));
@@ -226,8 +216,7 @@ public:
}
/* Check if given mem-comparable key belongs to this index */
bool covers_key(const rocksdb::Slice &slice) const
{
bool covers_key(const rocksdb::Slice &slice) const {
if (slice.size() < INDEX_NUMBER_SIZE)
return false;
@@ -244,43 +233,35 @@ public:
form)
*/
bool value_matches_prefix(const rocksdb::Slice &value,
const rocksdb::Slice &prefix) const
{
const rocksdb::Slice &prefix) const {
return covers_key(value) && !cmp_full_keys(value, prefix);
}
uint32 get_keyno() const
{
return m_keyno;
}
uint32 get_keyno() const { return m_keyno; }
uint32 get_index_number() const
{
return m_index_number;
}
uint32 get_index_number() const { return m_index_number; }
GL_INDEX_ID get_gl_index_id() const
{
GL_INDEX_ID get_gl_index_id() const {
const GL_INDEX_ID gl_index_id = {m_cf_handle->GetID(), m_index_number};
return gl_index_id;
}
int read_memcmp_key_part(const TABLE *table_arg, Rdb_string_reader *reader,
const uint part_num) const;
/* Must only be called for secondary keys: */
uint get_primary_key_tuple(const TABLE *const tbl,
const Rdb_key_def &pk_descr,
const rocksdb::Slice *const key,
uchar *const pk_buffer) const;
/* Return max length of mem-comparable form */
uint max_storage_fmt_length() const
{
return m_maxlength;
}
uint get_memcmp_sk_parts(const TABLE *table, const rocksdb::Slice &key,
uchar *sk_buffer, uint *n_null_fields) const;
uint get_key_parts() const
{
return m_key_parts;
}
/* Return max length of mem-comparable form */
uint max_storage_fmt_length() const { return m_maxlength; }
uint get_key_parts() const { return m_key_parts; }
/*
Get a field object for key part #part_no
@@ -294,19 +275,19 @@ public:
*/
inline Field *get_table_field_for_part_no(TABLE *table, uint part_no) const;
const std::string& get_name() const {
return m_name;
const std::string &get_name() const { return m_name; }
const rocksdb::SliceTransform *get_extractor() const {
return m_prefix_extractor.get();
}
Rdb_key_def &operator=(const Rdb_key_def &) = delete;
Rdb_key_def(const Rdb_key_def &k);
Rdb_key_def(uint indexnr_arg, uint keyno_arg,
rocksdb::ColumnFamilyHandle *cf_handle_arg,
uint16_t index_dict_version_arg,
uchar index_type_arg,
uint16_t kv_format_version_arg,
bool is_reverse_cf_arg, bool is_auto_cf_arg,
const char* name,
uint16_t index_dict_version_arg, uchar index_type_arg,
uint16_t kv_format_version_arg, bool is_reverse_cf_arg,
bool is_auto_cf_arg, const char *name,
Rdb_index_stats stats = Rdb_index_stats());
~Rdb_key_def();
@@ -410,10 +391,8 @@ public:
bool index_format_min_check(const int &pk_min, const int &sk_min) const;
private:
#ifndef DBUG_OFF
inline bool is_storage_available(const int &offset, const int &needed) const
{
inline bool is_storage_available(const int &offset, const int &needed) const {
const int storage_length = static_cast<int>(max_storage_fmt_length());
return (storage_length - offset) >= needed;
}
@@ -437,8 +416,8 @@ public:
bool m_is_auto_cf;
std::string m_name;
mutable Rdb_index_stats m_stats;
private:
private:
friend class Rdb_tbl_def; // for m_index_number above
/* Number of key parts in the primary key*/
@@ -461,6 +440,9 @@ private:
*/
uint m_key_parts;
/* Prefix extractor for the column family of the key definiton */
std::shared_ptr<const rocksdb::SliceTransform> m_prefix_extractor;
/* Maximum length of the mem-comparable form. */
uint m_maxlength;
@@ -485,8 +467,7 @@ private:
//
// We have m_dec_idx[idx][dst] = src to get our original character back.
//
struct Rdb_collation_codec
{
struct Rdb_collation_codec {
const my_core::CHARSET_INFO *m_cs;
// The first element unpacks VARCHAR(n), the second one - CHAR(n).
std::array<rdb_make_unpack_info_t, 2> m_make_unpack_info_func;
@@ -504,9 +485,7 @@ extern mysql_mutex_t rdb_mem_cmp_space_mutex;
extern std::array<const Rdb_collation_codec *, MY_ALL_CHARSETS_SIZE>
rdb_collation_data;
class Rdb_field_packing
{
class Rdb_field_packing {
public:
Rdb_field_packing(const Rdb_field_packing &) = delete;
Rdb_field_packing &operator=(const Rdb_field_packing &) = delete;
@@ -542,10 +521,7 @@ public:
/*
@return TRUE: this field makes use of unpack_info.
*/
bool uses_unpack_info() const
{
return (m_make_unpack_info_func != nullptr);
}
bool uses_unpack_info() const { return (m_make_unpack_info_func != nullptr); }
/* TRUE means unpack_info stores the original field value */
bool m_unpack_info_stores_value;
@@ -591,6 +567,7 @@ private:
*/
uint m_keynr;
uint m_key_part;
public:
bool setup(const Rdb_key_def *const key_descr, const Field *const field,
const uint &keynr_arg, const uint &key_part_arg,
@@ -606,8 +583,7 @@ public:
For encoding/decoding of index tuples, see Rdb_key_def.
*/
class Rdb_field_encoder
{
class Rdb_field_encoder {
public:
Rdb_field_encoder(const Rdb_field_encoder &) = delete;
Rdb_field_encoder &operator=(const Rdb_field_encoder &) = delete;
@@ -637,33 +613,28 @@ class Rdb_field_encoder
bool maybe_null() const { return m_null_mask != 0; }
bool uses_variable_len_encoding() const
{
bool uses_variable_len_encoding() const {
return (m_field_type == MYSQL_TYPE_BLOB ||
m_field_type == MYSQL_TYPE_VARCHAR);
}
};
inline Field *Rdb_key_def::get_table_field_for_part_no(TABLE *table,
uint part_no) const
{
uint part_no) const {
DBUG_ASSERT(part_no < get_key_parts());
return m_pack_info[part_no].get_field_in_table(table);
}
inline bool Rdb_key_def::can_unpack(const uint &kp) const
{
inline bool Rdb_key_def::can_unpack(const uint &kp) const {
DBUG_ASSERT(kp < m_key_parts);
return (m_pack_info[kp].m_unpack_func != nullptr);
}
inline bool Rdb_key_def::has_unpack_info(const uint &kp) const
{
inline bool Rdb_key_def::has_unpack_info(const uint &kp) const {
DBUG_ASSERT(kp < m_key_parts);
return m_pack_info[kp].uses_unpack_info();
}
/*
A table definition. This is an entry in the mapping
@@ -673,8 +644,7 @@ inline bool Rdb_key_def::has_unpack_info(const uint &kp) const
That's why we keep auto_increment value here, too.
*/
class Rdb_tbl_def
{
class Rdb_tbl_def {
private:
void check_if_is_mysql_system_table();
@@ -692,21 +662,18 @@ class Rdb_tbl_def
Rdb_tbl_def(const Rdb_tbl_def &) = delete;
Rdb_tbl_def &operator=(const Rdb_tbl_def &) = delete;
explicit Rdb_tbl_def(const std::string& name) :
m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1)
{
explicit Rdb_tbl_def(const std::string &name)
: m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1) {
set_name(name);
}
Rdb_tbl_def(const char* const name, const size_t &len) :
m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1)
{
Rdb_tbl_def(const char *const name, const size_t &len)
: m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1) {
set_name(std::string(name, len));
}
explicit Rdb_tbl_def(const rocksdb::Slice& slice, const size_t &pos= 0) :
m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1)
{
explicit Rdb_tbl_def(const rocksdb::Slice &slice, const size_t &pos = 0)
: m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1) {
set_name(std::string(slice.data() + pos, slice.size() - pos));
}
@@ -733,43 +700,35 @@ class Rdb_tbl_def
const std::string &base_partition() const { return m_partition; }
};
/*
A thread-safe sequential number generator. Its performance is not a concern
hence it is ok to protect it by a mutex.
*/
class Rdb_seq_generator
{
class Rdb_seq_generator {
uint m_next_number = 0;
mysql_mutex_t m_mutex;
public:
Rdb_seq_generator(const Rdb_seq_generator &) = delete;
Rdb_seq_generator &operator=(const Rdb_seq_generator &) = delete;
Rdb_seq_generator() = default;
void init(const uint &initial_number)
{
void init(const uint &initial_number) {
mysql_mutex_init(0, &m_mutex, MY_MUTEX_INIT_FAST);
m_next_number = initial_number;
}
uint get_and_update_next_number(Rdb_dict_manager *const dict);
void cleanup()
{
mysql_mutex_destroy(&m_mutex);
}
void cleanup() { mysql_mutex_destroy(&m_mutex); }
};
interface Rdb_tables_scanner
{
interface Rdb_tables_scanner {
virtual int add_table(Rdb_tbl_def * tdef) = 0;
};
/*
This contains a mapping of
@@ -778,8 +737,7 @@ interface Rdb_tables_scanner
objects are shared among all threads.
*/
class Rdb_ddl_manager
{
class Rdb_ddl_manager {
Rdb_dict_manager *m_dict = nullptr;
my_core::HASH m_ddl_hash; // Contains Rdb_tbl_def elements
// maps index id to <table_name, index number>
@@ -792,8 +750,8 @@ class Rdb_ddl_manager
// and consumed by the rocksdb background thread
std::map<GL_INDEX_ID, Rdb_index_stats> m_stats2store;
const std::shared_ptr<Rdb_key_def>& find(
GL_INDEX_ID gl_index_id);
const std::shared_ptr<Rdb_key_def> &find(GL_INDEX_ID gl_index_id);
public:
Rdb_ddl_manager(const Rdb_ddl_manager &) = delete;
Rdb_ddl_manager &operator=(const Rdb_ddl_manager &) = delete;
@@ -807,12 +765,10 @@ public:
Rdb_tbl_def *find(const std::string &table_name, const bool &lock = true);
std::shared_ptr<const Rdb_key_def> safe_find(GL_INDEX_ID gl_index_id);
void set_stats(
const std::unordered_map<GL_INDEX_ID, Rdb_index_stats>& stats);
void adjust_stats(
const std::vector<Rdb_index_stats>& new_data,
const std::vector<Rdb_index_stats>& deleted_data
=std::vector<Rdb_index_stats>());
void set_stats(const std::unordered_map<GL_INDEX_ID, Rdb_index_stats> &stats);
void adjust_stats(const std::vector<Rdb_index_stats> &new_data,
const std::vector<Rdb_index_stats> &deleted_data =
std::vector<Rdb_index_stats>());
void persist_stats(const bool &sync = false);
/* Modify the mapping and write it to on-disk storage */
@@ -823,8 +779,9 @@ public:
bool rename(const std::string &from, const std::string &to,
rocksdb::WriteBatch *const batch);
uint get_and_update_next_number(Rdb_dict_manager* const dict)
{ return m_sequence.get_and_update_next_number(dict); }
uint get_and_update_next_number(Rdb_dict_manager *const dict) {
return m_sequence.get_and_update_next_number(dict);
}
/* Walk the data dictionary */
int scan_for_tables(Rdb_tables_scanner *tables_scanner);
@@ -837,13 +794,12 @@ private:
/* Helper functions to be passed to my_core::HASH object */
static const uchar *get_hash_key(Rdb_tbl_def *const rec, size_t *const length,
my_bool not_used __attribute__((unused)));
my_bool not_used MY_ATTRIBUTE((unused)));
static void free_hash_elem(void *const data);
bool validate_schemas();
};
/*
Writing binlog information into RocksDB at commit(),
and retrieving binlog information at crash recovery.
@@ -859,8 +815,7 @@ private:
binlog_gtid_length (2 byte form)
binlog_gtid
*/
class Rdb_binlog_manager
{
class Rdb_binlog_manager {
public:
Rdb_binlog_manager(const Rdb_binlog_manager &) = delete;
Rdb_binlog_manager &operator=(const Rdb_binlog_manager &) = delete;
@@ -882,8 +837,7 @@ private:
uchar m_key_buf[Rdb_key_def::INDEX_NUMBER_SIZE] = {0};
rocksdb::Slice m_key_slice;
rocksdb::Slice pack_value(uchar* const buf,
const char* const binlog_name,
rocksdb::Slice pack_value(uchar *const buf, const char *const binlog_name,
const my_off_t &binlog_pos,
const char *const binlog_gtid) const;
bool unpack_value(const uchar *const value, char *const binlog_name,
@@ -892,7 +846,6 @@ private:
std::atomic<Rdb_tbl_def *> m_slave_gtid_info_tbl;
};
/*
Rdb_dict_manager manages how MySQL on RocksDB (MyRocks) stores its
internal data dictionary.
@@ -944,8 +897,7 @@ private:
begin() and commit() to make it easier to do atomic operations.
*/
class Rdb_dict_manager
{
class Rdb_dict_manager {
private:
mysql_mutex_t m_mutex;
rocksdb::DB *m_db = nullptr;
@@ -968,6 +920,7 @@ private:
const char *const log_action) const;
void log_start_drop_index(GL_INDEX_ID gl_index_id,
const char *log_action) const;
public:
Rdb_dict_manager(const Rdb_dict_manager &) = delete;
Rdb_dict_manager &operator=(const Rdb_dict_manager &) = delete;
@@ -975,20 +928,11 @@ public:
bool init(rocksdb::DB *const rdb_dict, Rdb_cf_manager *const cf_manager);
inline void cleanup()
{
mysql_mutex_destroy(&m_mutex);
}
inline void cleanup() { mysql_mutex_destroy(&m_mutex); }
inline void lock()
{
mysql_mutex_lock(&m_mutex);
}
inline void lock() { mysql_mutex_lock(&m_mutex); }
inline void unlock()
{
mysql_mutex_unlock(&m_mutex);
}
inline void unlock() { mysql_mutex_unlock(&m_mutex); }
/* Raw RocksDB operations */
std::unique_ptr<rocksdb::WriteBatch> begin() const;
@@ -1010,17 +954,17 @@ public:
void delete_index_info(rocksdb::WriteBatch *batch,
const GL_INDEX_ID &index_id) const;
bool get_index_info(const GL_INDEX_ID &gl_index_id,
uint16_t *index_dict_version,
uchar *index_type, uint16_t *kv_version) const;
uint16_t *index_dict_version, uchar *index_type,
uint16_t *kv_version) const;
/* CF id => CF flags */
void add_cf_flags(rocksdb::WriteBatch* const batch,
const uint &cf_id,
void add_cf_flags(rocksdb::WriteBatch *const batch, const uint &cf_id,
const uint &cf_flags) const;
bool get_cf_flags(const uint &cf_id, uint *const cf_flags) const;
/* Functions for fast CREATE/DROP TABLE/INDEX */
void get_ongoing_index_operation(std::vector<GL_INDEX_ID>* gl_index_ids,
void
get_ongoing_index_operation(std::unordered_set<GL_INDEX_ID> *gl_index_ids,
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
bool is_index_operation_ongoing(const GL_INDEX_ID &gl_index_id,
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
@@ -1038,54 +982,45 @@ public:
rocksdb::WriteBatch *const batch) const;
void add_create_index(const std::unordered_set<GL_INDEX_ID> &gl_index_ids,
rocksdb::WriteBatch *const batch) const;
void finish_indexes_operation(
const std::unordered_set<GL_INDEX_ID>& gl_index_ids,
void
finish_indexes_operation(const std::unordered_set<GL_INDEX_ID> &gl_index_ids,
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
void rollback_ongoing_index_creation() const;
inline void
get_ongoing_drop_indexes(std::vector<GL_INDEX_ID>* gl_index_ids) const
{
inline void get_ongoing_drop_indexes(
std::unordered_set<GL_INDEX_ID> *gl_index_ids) const {
get_ongoing_index_operation(gl_index_ids,
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
}
inline void
get_ongoing_create_indexes(std::vector<GL_INDEX_ID>* gl_index_ids) const
{
inline void get_ongoing_create_indexes(
std::unordered_set<GL_INDEX_ID> *gl_index_ids) const {
get_ongoing_index_operation(gl_index_ids,
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
}
inline void start_drop_index(rocksdb::WriteBatch *wb,
const GL_INDEX_ID& gl_index_id) const
{
const GL_INDEX_ID &gl_index_id) const {
start_ongoing_index_operation(wb, gl_index_id,
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
}
inline void start_create_index(rocksdb::WriteBatch *wb,
const GL_INDEX_ID& gl_index_id) const
{
const GL_INDEX_ID &gl_index_id) const {
start_ongoing_index_operation(wb, gl_index_id,
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
}
inline void finish_drop_indexes(
const std::unordered_set<GL_INDEX_ID>& gl_index_ids) const
{
finish_indexes_operation(gl_index_ids,
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
const std::unordered_set<GL_INDEX_ID> &gl_index_ids) const {
finish_indexes_operation(gl_index_ids, Rdb_key_def::DDL_DROP_INDEX_ONGOING);
}
inline void finish_create_indexes(
const std::unordered_set<GL_INDEX_ID>& gl_index_ids) const
{
const std::unordered_set<GL_INDEX_ID> &gl_index_ids) const {
finish_indexes_operation(gl_index_ids,
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
}
inline bool is_drop_index_ongoing(const GL_INDEX_ID& gl_index_id) const
{
inline bool is_drop_index_ongoing(const GL_INDEX_ID &gl_index_id) const {
return is_index_operation_ongoing(gl_index_id,
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
}
inline bool is_create_index_ongoing(const GL_INDEX_ID& gl_index_id) const
{
inline bool is_create_index_ongoing(const GL_INDEX_ID &gl_index_id) const {
return is_index_operation_ongoing(gl_index_id,
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,10 +26,10 @@ extern struct st_mysql_plugin rdb_i_s_dbstats;
extern struct st_mysql_plugin rdb_i_s_perf_context;
extern struct st_mysql_plugin rdb_i_s_perf_context_global;
extern struct st_mysql_plugin rdb_i_s_cfoptions;
extern struct st_mysql_plugin rdb_i_s_compact_stats;
extern struct st_mysql_plugin rdb_i_s_global_info;
extern struct st_mysql_plugin rdb_i_s_ddl;
extern struct st_mysql_plugin rdb_i_s_index_file_map;
extern struct st_mysql_plugin rdb_i_s_lock_info;
extern struct st_mysql_plugin rdb_i_s_trx_info;
} // namespace myrocks

View File

@@ -17,6 +17,9 @@
/* This C++ file's header file */
#include "./rdb_index_merge.h"
/* MySQL header files */
#include "../sql/sql_class.h"
/* MyRocks header files */
#include "./ha_rocksdb.h"
#include "./rdb_datadic.h"
@@ -26,38 +29,25 @@ namespace myrocks {
Rdb_index_merge::Rdb_index_merge(const char *const tmpfile_path,
const ulonglong &merge_buf_size,
const ulonglong &merge_combine_read_size,
const rocksdb::Comparator* const comparator) :
m_tmpfile_path(tmpfile_path),
m_merge_buf_size(merge_buf_size),
const rocksdb::Comparator *const comparator)
: m_tmpfile_path(tmpfile_path), m_merge_buf_size(merge_buf_size),
m_merge_combine_read_size(merge_combine_read_size),
m_comparator(comparator),
m_rec_buf_unsorted(nullptr),
m_output_buf(nullptr)
{
}
m_comparator(comparator), m_rec_buf_unsorted(nullptr),
m_output_buf(nullptr) {}
Rdb_index_merge::~Rdb_index_merge()
{
Rdb_index_merge::~Rdb_index_merge() {
/*
Close tmp file, we don't need to worry about deletion, mysql handles it.
*/
my_close(m_merge_file.fd, MYF(MY_WME));
/* There should be no records left in the offset tree */
DBUG_ASSERT(m_offset_tree.empty());
/* There should be no pointers left on the merge heap */
DBUG_ASSERT(m_merge_min_heap.empty());
}
int Rdb_index_merge::init()
{
int Rdb_index_merge::init() {
/*
Create a temporary merge file on disk to store sorted chunks during
inplace index creation.
*/
if (merge_file_create())
{
if (merge_file_create()) {
return HA_ERR_INTERNAL_ERROR;
}
@@ -66,46 +56,41 @@ int Rdb_index_merge::init()
to disk. They will be written to disk sorted. A sorted tree is used to
keep track of the offset of each record within the unsorted buffer.
*/
m_rec_buf_unsorted= std::shared_ptr<merge_buf_info>(
new merge_buf_info(m_merge_buf_size));
m_rec_buf_unsorted =
std::shared_ptr<merge_buf_info>(new merge_buf_info(m_merge_buf_size));
/*
Allocate output buffer that will contain sorted block that is written to
disk.
*/
m_output_buf= std::shared_ptr<merge_buf_info>(
new merge_buf_info(m_merge_buf_size));
m_output_buf =
std::shared_ptr<merge_buf_info>(new merge_buf_info(m_merge_buf_size));
return 0;
return HA_EXIT_SUCCESS;
}
/**
Create a merge file in the given location.
*/
int Rdb_index_merge::merge_file_create()
{
int Rdb_index_merge::merge_file_create() {
DBUG_ASSERT(m_merge_file.fd == -1);
int fd;
/* If no path set for tmpfile, use mysql_tmpdir by default */
if (m_tmpfile_path == nullptr)
{
if (m_tmpfile_path == nullptr) {
fd = mysql_tmpfile("myrocks");
}
else
{
} else {
fd = mysql_tmpfile_path(m_tmpfile_path, "myrocks");
}
if (fd < 0)
{
if (fd < 0) {
return HA_ERR_INTERNAL_ERROR;
}
m_merge_file.fd = fd;
m_merge_file.num_sort_buffers = 0;
return 0;
return HA_EXIT_SUCCESS;
}
/**
@@ -115,9 +100,7 @@ int Rdb_index_merge::merge_file_create()
If buffer in memory is full, write the buffer out to disk sorted using the
offset tree, and clear the tree. (Happens in merge_buf_write)
*/
int Rdb_index_merge::add(const rocksdb::Slice& key,
const rocksdb::Slice& val)
{
int Rdb_index_merge::add(const rocksdb::Slice &key, const rocksdb::Slice &val) {
/* Adding a record after heap is already created results in error */
DBUG_ASSERT(m_merge_min_heap.empty());
@@ -125,26 +108,23 @@ int Rdb_index_merge::add(const rocksdb::Slice& key,
Check if sort buffer is going to be out of space, if so write it
out to disk in sorted order using offset tree.
*/
const uint total_offset=
RDB_MERGE_CHUNK_LEN + m_rec_buf_unsorted->curr_offset +
const uint total_offset = RDB_MERGE_CHUNK_LEN +
m_rec_buf_unsorted->curr_offset +
RDB_MERGE_KEY_DELIMITER + RDB_MERGE_VAL_DELIMITER +
key.size() + val.size();
if (total_offset >= m_rec_buf_unsorted->total_size)
{
if (total_offset >= m_rec_buf_unsorted->total_size) {
/*
If the offset tree is empty here, that means that the proposed key to
add is too large for the buffer.
*/
if (m_offset_tree.empty())
{
if (m_offset_tree.empty()) {
// NO_LINT_DEBUG
sql_print_error("Sort buffer size is too small to process merge. "
"Please set merge buffer size to a higher value.");
return HA_ERR_INTERNAL_ERROR;
}
if (merge_buf_write())
{
if (merge_buf_write()) {
// NO_LINT_DEBUG
sql_print_error("Error writing sort buffer to disk.");
return HA_ERR_INTERNAL_ERROR;
@@ -163,14 +143,13 @@ int Rdb_index_merge::add(const rocksdb::Slice& key,
m_offset_tree.emplace(m_rec_buf_unsorted->block.get() + rec_offset,
m_comparator);
return 0;
return HA_EXIT_SUCCESS;
}
/**
Sort + write merge buffer chunk out to disk.
*/
int Rdb_index_merge::merge_buf_write()
{
int Rdb_index_merge::merge_buf_write() {
DBUG_ASSERT(m_merge_file.fd != -1);
DBUG_ASSERT(m_rec_buf_unsorted != nullptr);
DBUG_ASSERT(m_output_buf != nullptr);
@@ -185,8 +164,7 @@ int Rdb_index_merge::merge_buf_write()
Iterate through the offset tree. Should be ordered by the secondary key
at this point.
*/
for (const auto& rec : m_offset_tree)
{
for (const auto &rec : m_offset_tree) {
DBUG_ASSERT(m_output_buf->curr_offset <= m_merge_buf_size);
/* Read record from offset (should never fail) */
@@ -207,8 +185,7 @@ int Rdb_index_merge::merge_buf_write()
then write into the respective merge buffer.
*/
if (my_seek(m_merge_file.fd, m_merge_file.num_sort_buffers * m_merge_buf_size,
SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
{
SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) {
// NO_LINT_DEBUG
sql_print_error("Error seeking to location in merge file on disk.");
return HA_ERR_INTERNAL_ERROR;
@@ -221,8 +198,7 @@ int Rdb_index_merge::merge_buf_write()
*/
if (my_write(m_merge_file.fd, m_output_buf->block.get(),
m_output_buf->total_size, MYF(MY_WME | MY_NABP)) ||
mysql_file_sync(m_merge_file.fd, MYF(MY_WME)))
{
mysql_file_sync(m_merge_file.fd, MYF(MY_WME))) {
// NO_LINT_DEBUG
sql_print_error("Error writing sorted merge buffer to disk.");
return HA_ERR_INTERNAL_ERROR;
@@ -234,23 +210,21 @@ int Rdb_index_merge::merge_buf_write()
/* Reset everything for next run */
merge_reset();
return 0;
return HA_EXIT_SUCCESS;
}
/**
Prepare n-way merge of n sorted buffers on disk, using a heap sorted by
secondary key records.
*/
int Rdb_index_merge::merge_heap_prepare()
{
int Rdb_index_merge::merge_heap_prepare() {
DBUG_ASSERT(m_merge_min_heap.empty());
/*
If the offset tree is not empty, there are still some records that need to
be written to disk. Write them out now.
*/
if (!m_offset_tree.empty() && merge_buf_write())
{
if (!m_offset_tree.empty() && merge_buf_write()) {
return HA_ERR_INTERNAL_ERROR;
}
@@ -260,16 +234,14 @@ int Rdb_index_merge::merge_heap_prepare()
For an n-way merge, we need to read chunks of each merge file
simultaneously.
*/
ulonglong chunk_size= m_merge_combine_read_size/
m_merge_file.num_sort_buffers;
if (chunk_size >= m_merge_buf_size)
{
ulonglong chunk_size =
m_merge_combine_read_size / m_merge_file.num_sort_buffers;
if (chunk_size >= m_merge_buf_size) {
chunk_size = m_merge_buf_size;
}
/* Allocate buffers for each chunk */
for (ulonglong i = 0; i < m_merge_file.num_sort_buffers; i++)
{
for (ulonglong i = 0; i < m_merge_file.num_sort_buffers; i++) {
const auto entry = std::make_shared<merge_heap_entry>(m_comparator);
/*
@@ -279,20 +251,17 @@ int Rdb_index_merge::merge_heap_prepare()
const size_t total_size =
entry->prepare(m_merge_file.fd, i * m_merge_buf_size, chunk_size);
if (total_size == (size_t) - 1)
{
if (total_size == (size_t)-1) {
return HA_ERR_INTERNAL_ERROR;
}
/* Can reach this condition if an index was added on table w/ no rows */
if (total_size - RDB_MERGE_CHUNK_LEN == 0)
{
if (total_size - RDB_MERGE_CHUNK_LEN == 0) {
break;
}
/* Read the first record from each buffer to initially populate the heap */
if (entry->read_rec(&entry->key, &entry->val))
{
if (entry->read_rec(&entry->key, &entry->val)) {
// NO_LINT_DEBUG
sql_print_error("Chunk size is too small to process merge.");
return HA_ERR_INTERNAL_ERROR;
@@ -301,14 +270,14 @@ int Rdb_index_merge::merge_heap_prepare()
m_merge_min_heap.push(std::move(entry));
}
return 0;
return HA_EXIT_SUCCESS;
}
/**
Create and/or iterate through keys in the merge heap.
*/
int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
{
int Rdb_index_merge::next(rocksdb::Slice *const key,
rocksdb::Slice *const val) {
/*
If table fits in one sort buffer, we can optimize by writing
the sort buffer directly through to the sstfilewriter instead of
@@ -317,10 +286,8 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
If there are no sort buffer records (alters on empty tables),
also exit here.
*/
if (m_merge_file.num_sort_buffers == 0)
{
if (m_offset_tree.empty())
{
if (m_merge_file.num_sort_buffers == 0) {
if (m_offset_tree.empty()) {
return -1;
}
@@ -330,7 +297,7 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
merge_read_rec(rec->block, key, val);
m_offset_tree.erase(rec);
return 0;
return HA_EXIT_SUCCESS;
}
int res;
@@ -340,10 +307,8 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
of the external sort. Populate the heap with initial values from each
disk chunk.
*/
if (m_merge_min_heap.empty())
{
if ((res= merge_heap_prepare()))
{
if (m_merge_min_heap.empty()) {
if ((res = merge_heap_prepare())) {
// NO_LINT_DEBUG
sql_print_error("Error during preparation of heap.");
return res;
@@ -354,7 +319,7 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
inside the SST file yet.
*/
merge_heap_top(key, val);
return 0;
return HA_EXIT_SUCCESS;
}
DBUG_ASSERT(!m_merge_min_heap.empty());
@@ -365,8 +330,7 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
Get current top record from the heap.
*/
void Rdb_index_merge::merge_heap_top(rocksdb::Slice *const key,
rocksdb::Slice* const val)
{
rocksdb::Slice *const val) {
DBUG_ASSERT(!m_merge_min_heap.empty());
const std::shared_ptr<merge_heap_entry> &entry = m_merge_min_heap.top();
@@ -381,8 +345,7 @@ void Rdb_index_merge::merge_heap_top(rocksdb::Slice* const key,
Returns -1 when there are no more records in the heap.
*/
int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice *const key,
rocksdb::Slice* const val)
{
rocksdb::Slice *const val) {
/*
Make a new reference to shared ptr so it doesn't get destroyed
during pop(). We are going to push this entry back onto the heap.
@@ -397,15 +360,13 @@ int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
Return without adding entry back onto heap.
If heap is also empty, we must be finished with merge.
*/
if (entry->chunk_info->is_chunk_finished())
{
if (m_merge_min_heap.empty())
{
if (entry->chunk_info->is_chunk_finished()) {
if (m_merge_min_heap.empty()) {
return -1;
}
merge_heap_top(key, val);
return 0;
return HA_EXIT_SUCCESS;
}
/*
@@ -417,16 +378,13 @@ int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
If merge_read_rec fails, it means the either the chunk was cut off
or we've reached the end of the respective chunk.
*/
if (entry->read_rec(&entry->key, &entry->val))
{
if (entry->read_next_chunk_from_disk(m_merge_file.fd))
{
if (entry->read_rec(&entry->key, &entry->val)) {
if (entry->read_next_chunk_from_disk(m_merge_file.fd)) {
return HA_ERR_INTERNAL_ERROR;
}
/* Try reading record again, should never fail. */
if (entry->read_rec(&entry->key, &entry->val))
{
if (entry->read_rec(&entry->key, &entry->val)) {
return HA_ERR_INTERNAL_ERROR;
}
}
@@ -436,52 +394,46 @@ int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
/* Return the current top record on heap */
merge_heap_top(key, val);
return 0;
return HA_EXIT_SUCCESS;
}
int Rdb_index_merge::merge_heap_entry::read_next_chunk_from_disk(File fd)
{
if (chunk_info->read_next_chunk_from_disk(fd))
{
return 1;
int Rdb_index_merge::merge_heap_entry::read_next_chunk_from_disk(File fd) {
if (chunk_info->read_next_chunk_from_disk(fd)) {
return HA_EXIT_FAILURE;
}
block = chunk_info->block.get();
return 0;
return HA_EXIT_SUCCESS;
}
int Rdb_index_merge::merge_buf_info::read_next_chunk_from_disk(File fd)
{
int Rdb_index_merge::merge_buf_info::read_next_chunk_from_disk(File fd) {
disk_curr_offset += curr_offset;
if (my_seek(fd, disk_curr_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
{
if (my_seek(fd, disk_curr_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) {
// NO_LINT_DEBUG
sql_print_error("Error seeking to location in merge file on disk.");
return 1;
return HA_EXIT_FAILURE;
}
/* Overwrite the old block */
const size_t bytes_read = my_read(fd, block.get(), block_len, MYF(MY_WME));
if (bytes_read == (size_t) -1)
{
if (bytes_read == (size_t)-1) {
// NO_LINT_DEBUG
sql_print_error("Error reading merge file from disk.");
return 1;
return HA_EXIT_FAILURE;
}
curr_offset = 0;
return 0;
return HA_EXIT_SUCCESS;
}
/**
Get records from offset within sort buffer and compare them.
Sort by least to greatest.
*/
int Rdb_index_merge::merge_record_compare(const uchar* const a_block,
const uchar* const b_block,
const rocksdb::Comparator* const comparator)
{
int Rdb_index_merge::merge_record_compare(
const uchar *const a_block, const uchar *const b_block,
const rocksdb::Comparator *const comparator) {
return comparator->Compare(as_slice(a_block), as_slice(b_block));
}
@@ -491,15 +443,14 @@ int Rdb_index_merge::merge_record_compare(const uchar* const a_block,
**/
void Rdb_index_merge::merge_read_rec(const uchar *const block,
rocksdb::Slice *const key,
rocksdb::Slice* const val)
{
rocksdb::Slice *const val) {
/* Read key at block offset into key slice and the value into value slice*/
read_slice(key, block);
read_slice(val, block + RDB_MERGE_REC_DELIMITER + key->size());
}
void Rdb_index_merge::read_slice(rocksdb::Slice* slice, const uchar* block_ptr)
{
void Rdb_index_merge::read_slice(rocksdb::Slice *slice,
const uchar *block_ptr) {
uint64 slice_len;
merge_read_uint64(&block_ptr, &slice_len);
@@ -507,69 +458,61 @@ void Rdb_index_merge::read_slice(rocksdb::Slice* slice, const uchar* block_ptr)
}
int Rdb_index_merge::merge_heap_entry::read_rec(rocksdb::Slice *const key,
rocksdb::Slice* const val)
{
rocksdb::Slice *const val) {
const uchar *block_ptr = block;
const auto orig_offset = chunk_info->curr_offset;
const auto orig_block = block;
/* Read key at block offset into key slice and the value into value slice*/
if (read_slice(key, &block_ptr) != 0)
{
return 1;
if (read_slice(key, &block_ptr) != 0) {
return HA_EXIT_FAILURE;
}
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
block += (uintptr_t)block_ptr - (uintptr_t)block;
if (read_slice(val, &block_ptr) != 0)
{
if (read_slice(val, &block_ptr) != 0) {
chunk_info->curr_offset = orig_offset;
block = orig_block;
return 1;
return HA_EXIT_FAILURE;
}
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
block += (uintptr_t)block_ptr - (uintptr_t)block;
return 0;
return HA_EXIT_SUCCESS;
}
int Rdb_index_merge::merge_heap_entry::read_slice(rocksdb::Slice *const slice,
const uchar** block_ptr)
{
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER))
{
return 1;
const uchar **block_ptr) {
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER)) {
return HA_EXIT_FAILURE;
}
uint64 slice_len;
merge_read_uint64(block_ptr, &slice_len);
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER + slice_len))
{
return 1;
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER + slice_len)) {
return HA_EXIT_FAILURE;
}
*slice= rocksdb::Slice(reinterpret_cast<const char*>(*block_ptr), slice_len);
*slice =
rocksdb::Slice(reinterpret_cast<const char *>(*block_ptr), slice_len);
*block_ptr += slice_len;
return 0;
return HA_EXIT_SUCCESS;
}
size_t Rdb_index_merge::merge_heap_entry::prepare(File fd, ulonglong f_offset,
ulonglong chunk_size)
{
ulonglong chunk_size) {
chunk_info = std::make_shared<merge_buf_info>(chunk_size);
const size_t res = chunk_info->prepare(fd, f_offset);
if (res != (size_t) - 1)
{
if (res != (size_t)-1) {
block = chunk_info->block.get() + RDB_MERGE_CHUNK_LEN;
}
return res;
}
size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset)
{
size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset) {
disk_start_offset = f_offset;
disk_curr_offset = f_offset;
@@ -577,16 +520,14 @@ size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset)
Need to position cursor to the chunk it needs to be at on filesystem
then read 'chunk_size' bytes into the respective chunk buffer.
*/
if (my_seek(fd, f_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
{
if (my_seek(fd, f_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) {
// NO_LINT_DEBUG
sql_print_error("Error seeking to location in merge file on disk.");
return (size_t)-1;
}
const size_t bytes_read = my_read(fd, block.get(), total_size, MYF(MY_WME));
if (bytes_read == (size_t) - 1)
{
if (bytes_read == (size_t)-1) {
// NO_LINT_DEBUG
sql_print_error("Error reading merge file from disk.");
return (size_t)-1;
@@ -604,14 +545,12 @@ size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset)
/* Store key and value w/ their respective delimiters at the given offset */
void Rdb_index_merge::merge_buf_info::store_key_value(
const rocksdb::Slice& key, const rocksdb::Slice& val)
{
const rocksdb::Slice &key, const rocksdb::Slice &val) {
store_slice(key);
store_slice(val);
}
void Rdb_index_merge::merge_buf_info::store_slice(const rocksdb::Slice& slice)
{
void Rdb_index_merge::merge_buf_info::store_slice(const rocksdb::Slice &slice) {
/* Store length delimiter */
merge_store_uint64(&block[curr_offset], slice.size());
@@ -622,9 +561,7 @@ void Rdb_index_merge::merge_buf_info::store_slice(const rocksdb::Slice& slice)
curr_offset += slice.size() + RDB_MERGE_REC_DELIMITER;
}
void Rdb_index_merge::merge_reset()
{
void Rdb_index_merge::merge_reset() {
/*
Either error, or all values in the sort buffer have been written to disk,
so we need to clear the offset tree.
@@ -632,14 +569,12 @@ void Rdb_index_merge::merge_reset()
m_offset_tree.clear();
/* Reset sort buffer block */
if (m_rec_buf_unsorted && m_rec_buf_unsorted->block)
{
if (m_rec_buf_unsorted && m_rec_buf_unsorted->block) {
m_rec_buf_unsorted->curr_offset = 0;
}
/* Reset output buf */
if (m_output_buf && m_output_buf->block)
{
if (m_output_buf && m_output_buf->block) {
m_output_buf->curr_offset = 0;
}
}

View File

@@ -22,9 +22,9 @@
#include "./my_global.h" /* ulonglong */
/* C++ standard header files */
#include <queue>
#include <set>
#include <vector>
#include <queue>
/* RocksDB header files */
#include "rocksdb/db.h"
@@ -60,38 +60,35 @@ class Rdb_index_merge {
struct merge_buf_info {
/* heap memory allocated for main memory sort/merge */
std::unique_ptr<uchar[]> block;
const ulonglong block_len; /* amount of data bytes allocated for block above */
const ulonglong
block_len; /* amount of data bytes allocated for block above */
ulonglong curr_offset; /* offset of the record pointer for the block */
ulonglong disk_start_offset; /* where the chunk starts on disk */
ulonglong disk_curr_offset; /* current offset on disk */
ulonglong total_size; /* total # of data bytes in chunk */
void store_key_value(const rocksdb::Slice &key, const rocksdb::Slice &val)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
void store_slice(const rocksdb::Slice& slice)
__attribute__((__nonnull__));
void store_slice(const rocksdb::Slice &slice) MY_ATTRIBUTE((__nonnull__));
size_t prepare(File fd, ulonglong f_offset)
__attribute__((__nonnull__));
size_t prepare(File fd, ulonglong f_offset) MY_ATTRIBUTE((__nonnull__));
int read_next_chunk_from_disk(File fd)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
inline bool is_chunk_finished() const
{
inline bool is_chunk_finished() const {
return curr_offset + disk_curr_offset - disk_start_offset == total_size;
}
inline bool has_space(uint64 needed) const
{
inline bool has_space(uint64 needed) const {
return curr_offset + needed <= block_len;
}
explicit merge_buf_info(const ulonglong merge_block_size) :
block(nullptr), block_len(merge_block_size), curr_offset(0),
disk_start_offset(0), disk_curr_offset(0), total_size(merge_block_size)
{
explicit merge_buf_info(const ulonglong merge_block_size)
: block(nullptr), block_len(merge_block_size), curr_offset(0),
disk_start_offset(0), disk_curr_offset(0),
total_size(merge_block_size) {
/* Will throw an exception if it runs out of memory here */
block = std::unique_ptr<uchar[]>(new uchar[merge_block_size]);
@@ -101,8 +98,7 @@ class Rdb_index_merge {
};
/* Represents an entry in the heap during merge phase of external sort */
struct merge_heap_entry
{
struct merge_heap_entry {
std::shared_ptr<merge_buf_info> chunk_info; /* pointer to buffer info */
uchar *block; /* pointer to heap memory where record is stored */
const rocksdb::Comparator *const comparator;
@@ -110,44 +106,40 @@ class Rdb_index_merge {
rocksdb::Slice val;
size_t prepare(File fd, ulonglong f_offset, ulonglong chunk_size)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
int read_next_chunk_from_disk(File fd)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int read_rec(rocksdb::Slice *const key, rocksdb::Slice *const val)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int read_slice(rocksdb::Slice *const slice, const uchar **block_ptr)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
explicit merge_heap_entry(const rocksdb::Comparator* const comparator) :
chunk_info(nullptr), block(nullptr), comparator(comparator) {}
explicit merge_heap_entry(const rocksdb::Comparator *const comparator)
: chunk_info(nullptr), block(nullptr), comparator(comparator) {}
};
struct merge_heap_comparator
{
struct merge_heap_comparator {
bool operator()(const std::shared_ptr<merge_heap_entry> &lhs,
const std::shared_ptr<merge_heap_entry>& rhs)
{
const std::shared_ptr<merge_heap_entry> &rhs) {
return lhs->comparator->Compare(rhs->key, lhs->key) < 0;
}
};
/* Represents a record in unsorted buffer */
struct merge_record
{
struct merge_record {
uchar *block; /* points to offset of key in sort buffer */
const rocksdb::Comparator *const comparator;
bool operator< (const merge_record &record) const
{
bool operator<(const merge_record &record) const {
return merge_record_compare(this->block, record.block, comparator) < 0;
}
merge_record(uchar *const block,
const rocksdb::Comparator* const comparator) :
block(block), comparator(comparator) {}
const rocksdb::Comparator *const comparator)
: block(block), comparator(comparator) {}
};
private:
@@ -161,22 +153,21 @@ class Rdb_index_merge {
std::set<merge_record> m_offset_tree;
std::priority_queue<std::shared_ptr<merge_heap_entry>,
std::vector<std::shared_ptr<merge_heap_entry>>,
merge_heap_comparator> m_merge_min_heap;
merge_heap_comparator>
m_merge_min_heap;
static inline void merge_store_uint64(uchar* const dst, uint64 n)
{
static inline void merge_store_uint64(uchar *const dst, uint64 n) {
memcpy(dst, &n, sizeof(n));
}
static inline void merge_read_uint64(const uchar **buf_ptr, uint64* const dst)
{
static inline void merge_read_uint64(const uchar **buf_ptr,
uint64 *const dst) {
DBUG_ASSERT(buf_ptr != nullptr);
memcpy(dst, *buf_ptr, sizeof(uint64));
*buf_ptr += sizeof(uint64);
}
static inline rocksdb::Slice as_slice(const uchar* block)
{
static inline rocksdb::Slice as_slice(const uchar *block) {
uint64 len;
merge_read_uint64(&block, &len);
@@ -185,14 +176,13 @@ class Rdb_index_merge {
static int merge_record_compare(const uchar *a_block, const uchar *b_block,
const rocksdb::Comparator *const comparator)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void merge_read_rec(const uchar *const block, rocksdb::Slice *const key,
rocksdb::Slice* const val)
__attribute__((__nonnull__));
rocksdb::Slice *const val) MY_ATTRIBUTE((__nonnull__));
void read_slice(rocksdb::Slice *slice, const uchar *block_ptr)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
public:
Rdb_index_merge(const char *const tmpfile_path,
@@ -201,30 +191,26 @@ class Rdb_index_merge {
const rocksdb::Comparator *const comparator);
~Rdb_index_merge();
int init()
__attribute__((__nonnull__, __warn_unused_result__));
int init() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int merge_file_create()
__attribute__((__nonnull__, __warn_unused_result__));
int merge_file_create() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int add(const rocksdb::Slice &key, const rocksdb::Slice &val)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int merge_buf_write()
__attribute__((__nonnull__, __warn_unused_result__));
int merge_buf_write() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int next(rocksdb::Slice *const key, rocksdb::Slice *const val)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
int merge_heap_prepare()
__attribute__((__nonnull__, __warn_unused_result__));
int merge_heap_prepare() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void merge_heap_top(rocksdb::Slice *key, rocksdb::Slice *val)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
int merge_heap_pop_and_get_next(rocksdb::Slice *const key,
rocksdb::Slice *const val)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
void merge_reset();
};

View File

@@ -17,43 +17,35 @@
/* This C++ file's header file */
#include "./rdb_mutex_wrapper.h"
/* MySQL header files */
#include "../sql/sql_class.h"
#include "../sql/replication.h"
/* MyRocks header files */
#include "./ha_rocksdb.h"
#include "./rdb_utils.h"
// Internal MySQL APIs not exposed in any header.
extern "C"
{
void thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, mysql_mutex_t *mutex,
const PSI_stage_info *stage, PSI_stage_info *old_stage);
void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage);
}
using namespace rocksdb;
namespace myrocks {
static
PSI_stage_info stage_waiting_on_row_lock2= { 0, "Waiting for row lock", 0};
static PSI_stage_info stage_waiting_on_row_lock2 = {0, "Waiting for row lock",
0};
static const int64_t MICROSECS= 1000*1000;
static const int64_t ONE_SECOND_IN_MICROSECS = 1000 * 1000;
// A timeout as long as one full non-leap year worth of microseconds is as
// good as infinite timeout.
static const int64_t BIG_TIMEOUT= MICROSECS * 60 * 60 * 24 * 365;
static const int64_t ONE_YEAR_IN_MICROSECS =
ONE_SECOND_IN_MICROSECS * 60 * 60 * 24 * 365;
Rdb_cond_var::Rdb_cond_var() {
mysql_cond_init(0, &m_cond, nullptr);
}
Rdb_cond_var::Rdb_cond_var() { mysql_cond_init(0, &m_cond, nullptr); }
Rdb_cond_var::~Rdb_cond_var() {
mysql_cond_destroy(&m_cond);
}
Rdb_cond_var::~Rdb_cond_var() { mysql_cond_destroy(&m_cond); }
Status Rdb_cond_var::Wait(const std::shared_ptr<TransactionDBMutex> mutex_arg) {
return WaitFor(mutex_arg, BIG_TIMEOUT);
return WaitFor(mutex_arg, ONE_YEAR_IN_MICROSECS);
}
/*
@brief
Wait on condition variable. The caller must make sure that we own
@@ -70,8 +62,7 @@ Status Rdb_cond_var::Wait(const std::shared_ptr<TransactionDBMutex> mutex_arg) {
Status
Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
int64_t timeout_micros)
{
int64_t timeout_micros) {
auto *mutex_obj = reinterpret_cast<Rdb_mutex *>(mutex_arg.get());
DBUG_ASSERT(mutex_obj != nullptr);
@@ -81,21 +72,20 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
struct timespec wait_timeout;
if (timeout_micros < 0)
timeout_micros= BIG_TIMEOUT;
timeout_micros = ONE_YEAR_IN_MICROSECS;
set_timespec_nsec(wait_timeout, timeout_micros * 1000);
#ifndef STANDALONE_UNITTEST
PSI_stage_info old_stage;
mysql_mutex_assert_owner(mutex_ptr);
if (current_thd && mutex_obj->m_old_stage_info.count(current_thd) == 0)
{
my_core::thd_enter_cond(current_thd, &m_cond, mutex_ptr,
&stage_waiting_on_row_lock2, &old_stage);
if (current_thd && mutex_obj->m_old_stage_info.count(current_thd) == 0) {
THD_ENTER_COND(current_thd, &m_cond, mutex_ptr, &stage_waiting_on_row_lock2,
&old_stage);
/*
After the mysql_cond_timedwait we need make this call
my_core::thd_exit_cond(thd, &old_stage);
THD_EXIT_COND(thd, &old_stage);
to inform the SQL layer that KILLable wait has ended. However,
that will cause mutex to be released. Defer the release until the mutex
@@ -107,8 +97,7 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
#endif
bool killed = false;
do
{
do {
res = mysql_cond_timedwait(&m_cond, mutex_ptr, &wait_timeout);
#ifndef STANDALONE_UNITTEST
@@ -123,7 +112,6 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
return Status::OK();
}
/*
@note
@@ -154,32 +142,21 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
None of this looks like a problem for our use case.
*/
void Rdb_cond_var::Notify()
{
mysql_cond_signal(&m_cond);
}
void Rdb_cond_var::Notify() { mysql_cond_signal(&m_cond); }
/*
@note
This is called without holding the mutex that's used for waiting on the
condition. See ::Notify().
*/
void Rdb_cond_var::NotifyAll()
{
mysql_cond_broadcast(&m_cond);
}
void Rdb_cond_var::NotifyAll() { mysql_cond_broadcast(&m_cond); }
Rdb_mutex::Rdb_mutex()
{
Rdb_mutex::Rdb_mutex() {
mysql_mutex_init(0 /* Don't register in P_S. */, &m_mutex,
MY_MUTEX_INIT_FAST);
}
Rdb_mutex::~Rdb_mutex() {
mysql_mutex_destroy(&m_mutex);
}
Rdb_mutex::~Rdb_mutex() { mysql_mutex_destroy(&m_mutex); }
Status Rdb_mutex::Lock() {
mysql_mutex_lock(&m_mutex);
@@ -192,8 +169,7 @@ Status Rdb_mutex::Lock() {
// If implementing a custom version of this class, the implementation may
// choose to ignore the timeout.
// Return OK on success, or other Status on failure.
Status Rdb_mutex::TryLockFor(int64_t timeout_time __attribute__((__unused__)))
{
Status Rdb_mutex::TryLockFor(int64_t timeout_time MY_ATTRIBUTE((__unused__))) {
/*
Note: PThreads API has pthread_mutex_timedlock(), but mysql's
mysql_mutex_* wrappers do not wrap that function.
@@ -202,10 +178,8 @@ Status Rdb_mutex::TryLockFor(int64_t timeout_time __attribute__((__unused__)))
return Status::OK();
}
#ifndef STANDALONE_UNITTEST
void Rdb_mutex::set_unlock_action(const PSI_stage_info* const old_stage_arg)
{
void Rdb_mutex::set_unlock_action(const PSI_stage_info *const old_stage_arg) {
DBUG_ASSERT(old_stage_arg != nullptr);
mysql_mutex_assert_owner(&m_mutex);
@@ -219,13 +193,12 @@ void Rdb_mutex::set_unlock_action(const PSI_stage_info* const old_stage_arg)
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
void Rdb_mutex::UnLock() {
#ifndef STANDALONE_UNITTEST
if (m_old_stage_info.count(current_thd) > 0)
{
if (m_old_stage_info.count(current_thd) > 0) {
const std::shared_ptr<PSI_stage_info> old_stage =
m_old_stage_info[current_thd];
m_old_stage_info.erase(current_thd);
/* The following will call mysql_mutex_unlock */
my_core::thd_exit_cond(current_thd, old_stage.get());
THD_EXIT_COND(current_thd, old_stage.get());
return;
}
#endif

View File

@@ -35,6 +35,7 @@ namespace myrocks {
class Rdb_mutex : public rocksdb::TransactionDBMutex {
Rdb_mutex(const Rdb_mutex &p) = delete;
Rdb_mutex &operator=(const Rdb_mutex &p) = delete;
public:
Rdb_mutex();
virtual ~Rdb_mutex();
@@ -53,8 +54,8 @@ class Rdb_mutex: public rocksdb::TransactionDBMutex {
// TimedOut if timed out,
// or other Status on failure.
// If returned status is OK, TransactionDB will eventually call UnLock().
virtual rocksdb::Status TryLockFor(
int64_t timeout_time __attribute__((__unused__))) override;
virtual rocksdb::Status
TryLockFor(int64_t timeout_time MY_ATTRIBUTE((__unused__))) override;
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
virtual void UnLock() override;
@@ -69,10 +70,10 @@ class Rdb_mutex: public rocksdb::TransactionDBMutex {
#endif
};
class Rdb_cond_var : public rocksdb::TransactionDBCondVar {
Rdb_cond_var(const Rdb_cond_var &) = delete;
Rdb_cond_var &operator=(const Rdb_cond_var &) = delete;
public:
Rdb_cond_var();
virtual ~Rdb_cond_var();
@@ -116,7 +117,6 @@ class Rdb_cond_var: public rocksdb::TransactionDBCondVar {
mysql_cond_t m_cond;
};
class Rdb_mutex_factory : public rocksdb::TransactionDBMutexFactory {
public:
Rdb_mutex_factory(const Rdb_mutex_factory &) = delete;
@@ -128,14 +128,12 @@ class Rdb_mutex_factory : public rocksdb::TransactionDBMutexFactory {
virtual std::shared_ptr<rocksdb::TransactionDBMutex>
AllocateMutex() override {
return
std::make_shared<Rdb_mutex>();
return std::make_shared<Rdb_mutex>();
}
virtual std::shared_ptr<rocksdb::TransactionDBCondVar>
AllocateCondVar() override {
return
std::make_shared<Rdb_cond_var>();
return std::make_shared<Rdb_cond_var>();
}
virtual ~Rdb_mutex_factory() {}

View File

@@ -35,8 +35,7 @@ namespace myrocks {
// 2. Update sections (A), (B), and (C) below
// 3. Update perf_context.test and show_engine.test
std::string rdb_pc_stat_types[]=
{
std::string rdb_pc_stat_types[] = {
// (A) These should be in the same order as the PC enum
"USER_KEY_COMPARISON_COUNT",
"BLOCK_CACHE_HIT_COUNT",
@@ -80,8 +79,7 @@ std::string rdb_pc_stat_types[]=
"IO_WRITE_NANOS",
"IO_READ_NANOS",
"IO_RANGE_SYNC_NANOS",
"IO_LOGGER_NANOS"
};
"IO_LOGGER_NANOS"};
#define IO_PERF_RECORD(_field_) \
do { \
@@ -96,8 +94,7 @@ std::string rdb_pc_stat_types[]=
idx++; \
} while (0)
static void harvest_diffs(Rdb_atomic_perf_counters * const counters)
{
static void harvest_diffs(Rdb_atomic_perf_counters *const counters) {
// (C) These should be in the same order as the PC enum
size_t idx = 0;
IO_PERF_RECORD(user_key_comparison_count);
@@ -148,35 +145,29 @@ static void harvest_diffs(Rdb_atomic_perf_counters * const counters)
#undef IO_PERF_DIFF
#undef IO_STAT_DIFF
static Rdb_atomic_perf_counters rdb_global_perf_counters;
void rdb_get_global_perf_counters(Rdb_perf_counters* const counters)
{
void rdb_get_global_perf_counters(Rdb_perf_counters *const counters) {
DBUG_ASSERT(counters != nullptr);
counters->load(rdb_global_perf_counters);
}
void Rdb_perf_counters::load(const Rdb_atomic_perf_counters &atomic_counters)
{
void Rdb_perf_counters::load(const Rdb_atomic_perf_counters &atomic_counters) {
for (int i = 0; i < PC_MAX_IDX; i++) {
m_value[i] = atomic_counters.m_value[i].load(std::memory_order_relaxed);
}
}
bool Rdb_io_perf::start(const uint32_t perf_context_level)
{
bool Rdb_io_perf::start(const uint32_t perf_context_level) {
const rocksdb::PerfLevel perf_level =
static_cast<rocksdb::PerfLevel>(perf_context_level);
if (rocksdb::GetPerfLevel() != perf_level)
{
if (rocksdb::GetPerfLevel() != perf_level) {
rocksdb::SetPerfLevel(perf_level);
}
if (perf_level == rocksdb::kDisable)
{
if (perf_level == rocksdb::kDisable) {
return false;
}
@@ -185,27 +176,22 @@ bool Rdb_io_perf::start(const uint32_t perf_context_level)
return true;
}
void Rdb_io_perf::end_and_record(const uint32_t perf_context_level)
{
void Rdb_io_perf::end_and_record(const uint32_t perf_context_level) {
const rocksdb::PerfLevel perf_level =
static_cast<rocksdb::PerfLevel>(perf_context_level);
if (perf_level == rocksdb::kDisable)
{
if (perf_level == rocksdb::kDisable) {
return;
}
if (m_atomic_counters)
{
if (m_atomic_counters) {
harvest_diffs(m_atomic_counters);
}
harvest_diffs(&rdb_global_perf_counters);
if (m_shared_io_perf_read &&
(rocksdb::perf_context.block_read_byte != 0 ||
if (m_shared_io_perf_read && (rocksdb::perf_context.block_read_byte != 0 ||
rocksdb::perf_context.block_read_count != 0 ||
rocksdb::perf_context.block_read_time != 0))
{
rocksdb::perf_context.block_read_time != 0)) {
my_io_perf_t io_perf_read;
io_perf_read.init();
@@ -224,13 +210,11 @@ void Rdb_io_perf::end_and_record(const uint32_t perf_context_level)
}
if (m_stats) {
if (rocksdb::perf_context.internal_key_skipped_count != 0)
{
if (rocksdb::perf_context.internal_key_skipped_count != 0) {
m_stats->key_skipped += rocksdb::perf_context.internal_key_skipped_count;
}
if (rocksdb::perf_context.internal_delete_skipped_count != 0)
{
if (rocksdb::perf_context.internal_delete_skipped_count != 0) {
m_stats->delete_skipped +=
rocksdb::perf_context.internal_delete_skipped_count;
}

View File

@@ -80,8 +80,7 @@ class Rdb_perf_counters;
A collection of performance counters that can be safely incremented by
multiple threads since it stores atomic datapoints.
*/
struct Rdb_atomic_perf_counters
{
struct Rdb_atomic_perf_counters {
std::atomic_ullong m_value[PC_MAX_IDX];
};
@@ -89,10 +88,10 @@ struct Rdb_atomic_perf_counters
A collection of performance counters that is meant to be incremented by
a single thread.
*/
class Rdb_perf_counters
{
class Rdb_perf_counters {
Rdb_perf_counters(const Rdb_perf_counters &) = delete;
Rdb_perf_counters &operator=(const Rdb_perf_counters &) = delete;
public:
Rdb_perf_counters() = default;
uint64_t m_value[PC_MAX_IDX];
@@ -105,8 +104,7 @@ extern std::string rdb_pc_stat_types[PC_MAX_IDX];
/*
Perf timers for data reads
*/
class Rdb_io_perf
{
class Rdb_io_perf {
// Context management
Rdb_atomic_perf_counters *m_atomic_counters = nullptr;
my_io_perf_atomic_t *m_shared_io_perf_read = nullptr;
@@ -118,8 +116,7 @@ class Rdb_io_perf
void init(Rdb_atomic_perf_counters *const atomic_counters,
my_io_perf_atomic_t *const shared_io_perf_read,
ha_statistics* const stats)
{
ha_statistics *const stats) {
DBUG_ASSERT(atomic_counters != nullptr);
DBUG_ASSERT(shared_io_perf_read != nullptr);
DBUG_ASSERT(stats != nullptr);
@@ -132,8 +129,8 @@ class Rdb_io_perf
bool start(const uint32_t perf_context_level);
void end_and_record(const uint32_t perf_context_level);
explicit Rdb_io_perf() : m_atomic_counters(nullptr),
m_shared_io_perf_read(nullptr),
explicit Rdb_io_perf()
: m_atomic_counters(nullptr), m_shared_io_perf_read(nullptr),
m_stats(nullptr) {}
};

View File

@@ -40,20 +40,14 @@ namespace myrocks {
Rdb_sst_file::Rdb_sst_file(rocksdb::DB *const db,
rocksdb::ColumnFamilyHandle *const cf,
const rocksdb::DBOptions &db_options,
const std::string& name, const bool tracing) :
m_db(db),
m_cf(cf),
m_db_options(db_options),
m_sst_file_writer(nullptr),
m_name(name),
m_tracing(tracing)
{
const std::string &name, const bool tracing)
: m_db(db), m_cf(cf), m_db_options(db_options), m_sst_file_writer(nullptr),
m_name(name), m_tracing(tracing) {
DBUG_ASSERT(db != nullptr);
DBUG_ASSERT(cf != nullptr);
}
Rdb_sst_file::~Rdb_sst_file()
{
Rdb_sst_file::~Rdb_sst_file() {
// Make sure we clean up
delete m_sst_file_writer;
m_sst_file_writer = nullptr;
@@ -64,15 +58,13 @@ Rdb_sst_file::~Rdb_sst_file()
std::remove(m_name.c_str());
}
rocksdb::Status Rdb_sst_file::open()
{
rocksdb::Status Rdb_sst_file::open() {
DBUG_ASSERT(m_sst_file_writer == nullptr);
rocksdb::ColumnFamilyDescriptor cf_descr;
rocksdb::Status s = m_cf->GetDescriptor(&cf_descr);
if (!s.ok())
{
if (!s.ok()) {
return s;
}
@@ -86,15 +78,13 @@ rocksdb::Status Rdb_sst_file::open()
new rocksdb::SstFileWriter(env_options, options, comparator, m_cf);
s = m_sst_file_writer->Open(m_name);
if (m_tracing)
{
if (m_tracing) {
// NO_LINT_DEBUG
sql_print_information("SST Tracing: Open(%s) returned %s", m_name.c_str(),
s.ok() ? "ok" : "not ok");
}
if (!s.ok())
{
if (!s.ok()) {
delete m_sst_file_writer;
m_sst_file_writer = nullptr;
}
@@ -103,27 +93,22 @@ rocksdb::Status Rdb_sst_file::open()
}
rocksdb::Status Rdb_sst_file::put(const rocksdb::Slice &key,
const rocksdb::Slice& value)
{
const rocksdb::Slice &value) {
DBUG_ASSERT(m_sst_file_writer != nullptr);
// Add the specified key/value to the sst file writer
return m_sst_file_writer->Add(key, value);
}
std::string Rdb_sst_file::generateKey(const std::string& key)
{
static char const hexdigit[]= {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
std::string Rdb_sst_file::generateKey(const std::string &key) {
static char const hexdigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
std::string res;
res.reserve(key.size() * 2);
for (auto ch : key)
{
for (auto ch : key) {
res += hexdigit[((uint8_t)ch) >> 4];
res += hexdigit[((uint8_t)ch) & 0x0F];
}
@@ -132,8 +117,7 @@ std::string Rdb_sst_file::generateKey(const std::string& key)
}
// This function is run by the background thread
rocksdb::Status Rdb_sst_file::commit()
{
rocksdb::Status Rdb_sst_file::commit() {
DBUG_ASSERT(m_sst_file_writer != nullptr);
rocksdb::Status s;
@@ -141,21 +125,19 @@ rocksdb::Status Rdb_sst_file::commit()
// Close out the sst file
s = m_sst_file_writer->Finish(&fileinfo);
if (m_tracing)
{
if (m_tracing) {
// NO_LINT_DEBUG
sql_print_information("SST Tracing: Finish returned %s",
s.ok() ? "ok" : "not ok");
}
if (s.ok())
{
if (m_tracing)
{
if (s.ok()) {
if (m_tracing) {
// NO_LINT_DEBUG
sql_print_information("SST Tracing: Adding file %s, smallest key: %s, "
"largest key: %s, file size: %" PRIu64 ", "
"num_entries: %" PRIu64, fileinfo.file_path.c_str(),
"num_entries: %" PRIu64,
fileinfo.file_path.c_str(),
generateKey(fileinfo.smallest_key).c_str(),
generateKey(fileinfo.largest_key).c_str(),
fileinfo.file_size, fileinfo.num_entries);
@@ -171,8 +153,7 @@ rocksdb::Status Rdb_sst_file::commit()
opts.allow_blocking_flush = false;
s = m_db->IngestExternalFile(m_cf, {m_name}, opts);
if (m_tracing)
{
if (m_tracing) {
// NO_LINT_DEBUG
sql_print_information("SST Tracing: AddFile(%s) returned %s",
fileinfo.file_path.c_str(),
@@ -190,64 +171,45 @@ Rdb_sst_info::Rdb_sst_info(rocksdb::DB* const db, const std::string& tablename,
const std::string &indexname,
rocksdb::ColumnFamilyHandle *const cf,
const rocksdb::DBOptions &db_options,
const bool& tracing) :
m_db(db),
m_cf(cf),
m_db_options(db_options),
m_curr_size(0),
m_sst_count(0),
m_error_msg(""),
const bool &tracing)
: m_db(db), m_cf(cf), m_db_options(db_options), m_curr_size(0),
m_sst_count(0), m_error_msg(""),
#if defined(RDB_SST_INFO_USE_THREAD)
m_queue(),
m_mutex(),
m_cond(),
m_thread(nullptr),
m_finished(false),
m_queue(), m_mutex(), m_cond(), m_thread(nullptr), m_finished(false),
#endif
m_sst_file(nullptr),
m_tracing(tracing)
{
m_sst_file(nullptr), m_tracing(tracing) {
m_prefix = db->GetName() + "/";
std::string normalized_table;
if (rdb_normalize_tablename(tablename.c_str(), &normalized_table))
{
if (rdb_normalize_tablename(tablename.c_str(), &normalized_table)) {
// We failed to get a normalized table name. This should never happen,
// but handle it anyway.
m_prefix += "fallback_" +
std::to_string(
reinterpret_cast<intptr_t>(reinterpret_cast<void*>(this))) + "_" +
indexname + "_";
}
else
{
m_prefix += "fallback_" + std::to_string(reinterpret_cast<intptr_t>(
reinterpret_cast<void *>(this))) +
"_" + indexname + "_";
} else {
m_prefix += normalized_table + "_" + indexname + "_";
}
rocksdb::ColumnFamilyDescriptor cf_descr;
const rocksdb::Status s = m_cf->GetDescriptor(&cf_descr);
if (!s.ok())
{
if (!s.ok()) {
// Default size if we can't get the cf's target size
m_max_size = 64 * 1024 * 1024;
}
else
{
} else {
// Set the maximum size to 3 times the cf's target size
m_max_size = cf_descr.options.target_file_size_base * 3;
}
}
Rdb_sst_info::~Rdb_sst_info()
{
Rdb_sst_info::~Rdb_sst_info() {
DBUG_ASSERT(m_sst_file == nullptr);
#if defined(RDB_SST_INFO_USE_THREAD)
DBUG_ASSERT(m_thread == nullptr);
#endif
}
int Rdb_sst_info::open_new_sst_file()
{
int Rdb_sst_info::open_new_sst_file() {
DBUG_ASSERT(m_sst_file == nullptr);
// Create the new sst file's name
@@ -258,27 +220,24 @@ int Rdb_sst_info::open_new_sst_file()
// Open the sst file
const rocksdb::Status s = m_sst_file->open();
if (!s.ok())
{
if (!s.ok()) {
set_error_msg(s.ToString());
delete m_sst_file;
m_sst_file = nullptr;
return 1;
return HA_EXIT_FAILURE;
}
m_curr_size = 0;
return 0;
return HA_EXIT_SUCCESS;
}
void Rdb_sst_info::close_curr_sst_file()
{
void Rdb_sst_info::close_curr_sst_file() {
DBUG_ASSERT(m_sst_file != nullptr);
DBUG_ASSERT(m_curr_size > 0);
#if defined(RDB_SST_INFO_USE_THREAD)
if (m_thread == nullptr)
{
if (m_thread == nullptr) {
// We haven't already started a background thread, so start one
m_thread = new std::thread(thread_fcn, this);
}
@@ -295,8 +254,7 @@ void Rdb_sst_info::close_curr_sst_file()
m_cond.notify_one();
#else
const rocksdb::Status s = m_sst_file->commit();
if (!s.ok())
{
if (!s.ok()) {
set_error_msg(s.ToString());
}
@@ -308,30 +266,24 @@ void Rdb_sst_info::close_curr_sst_file()
m_curr_size = 0;
}
int Rdb_sst_info::put(const rocksdb::Slice& key,
const rocksdb::Slice& value)
{
int Rdb_sst_info::put(const rocksdb::Slice &key, const rocksdb::Slice &value) {
int rc;
if (m_curr_size >= m_max_size)
{
if (m_curr_size >= m_max_size) {
// The current sst file has reached its maximum, close it out
close_curr_sst_file();
// While we are here, check to see if we have had any errors from the
// background thread - we don't want to wait for the end to report them
if (!m_error_msg.empty())
{
return 1;
if (!m_error_msg.empty()) {
return HA_EXIT_FAILURE;
}
}
if (m_curr_size == 0)
{
if (m_curr_size == 0) {
// We don't have an sst file open - open one
rc = open_new_sst_file();
if (rc != 0)
{
if (rc != 0) {
return rc;
}
}
@@ -340,28 +292,24 @@ int Rdb_sst_info::put(const rocksdb::Slice& key,
// Add the key/value to the current sst file
const rocksdb::Status s = m_sst_file->put(key, value);
if (!s.ok())
{
if (!s.ok()) {
set_error_msg(s.ToString());
return 1;
return HA_EXIT_FAILURE;
}
m_curr_size += key.size() + value.size();
return 0;
return HA_EXIT_SUCCESS;
}
int Rdb_sst_info::commit()
{
if (m_curr_size > 0)
{
int Rdb_sst_info::commit() {
if (m_curr_size > 0) {
// Close out any existing files
close_curr_sst_file();
}
#if defined(RDB_SST_INFO_USE_THREAD)
if (m_thread != nullptr)
{
if (m_thread != nullptr) {
// Tell the background thread we are done
m_finished = true;
m_cond.notify_one();
@@ -374,16 +322,14 @@ int Rdb_sst_info::commit()
#endif
// Did we get any errors?
if (!m_error_msg.empty())
{
return 1;
if (!m_error_msg.empty()) {
return HA_EXIT_FAILURE;
}
return 0;
return HA_EXIT_SUCCESS;
}
void Rdb_sst_info::set_error_msg(const std::string& msg)
{
void Rdb_sst_info::set_error_msg(const std::string &msg) {
#if defined(RDB_SST_INFO_USE_THREAD)
// Both the foreground and background threads can set the error message
// so lock the mutex to protect it. We only want the first error that
@@ -391,31 +337,26 @@ void Rdb_sst_info::set_error_msg(const std::string& msg)
const std::lock_guard<std::mutex> guard(m_mutex);
#endif
my_printf_error(ER_UNKNOWN_ERROR, "bulk load error: %s", MYF(0), msg.c_str());
if (m_error_msg.empty())
{
if (m_error_msg.empty()) {
m_error_msg = msg;
}
}
#if defined(RDB_SST_INFO_USE_THREAD)
// Static thread function - the Rdb_sst_info object is in 'object'
void Rdb_sst_info::thread_fcn(void* object)
{
void Rdb_sst_info::thread_fcn(void *object) {
reinterpret_cast<Rdb_sst_info *>(object)->run_thread();
}
void Rdb_sst_info::run_thread()
{
void Rdb_sst_info::run_thread() {
const std::unique_lock<std::mutex> lk(m_mutex);
do
{
do {
// Wait for notification or 1 second to pass
m_cond.wait_for(lk, std::chrono::seconds(1));
// Inner loop pulls off all Rdb_sst_file entries and processes them
while (!m_queue.empty())
{
while (!m_queue.empty()) {
const Rdb_sst_file *const sst_file = m_queue.front();
m_queue.pop();
@@ -424,8 +365,7 @@ void Rdb_sst_info::run_thread()
// Close out the sst file and add it to the database
const rocksdb::Status s = sst_file->commit();
if (!s.ok())
{
if (!s.ok()) {
set_error_msg(s.ToString());
}
@@ -443,14 +383,12 @@ void Rdb_sst_info::run_thread()
}
#endif
void Rdb_sst_info::init(const rocksdb::DB* const db)
{
void Rdb_sst_info::init(const rocksdb::DB *const db) {
const std::string path = db->GetName() + FN_DIRSEP;
struct st_my_dir *const dir_info = my_dir(path.c_str(), MYF(MY_DONT_SORT));
// Access the directory
if (dir_info == nullptr)
{
if (dir_info == nullptr) {
// NO_LINT_DEBUG
sql_print_warning("RocksDB: Could not access database directory: %s",
path.c_str());
@@ -459,13 +397,11 @@ void Rdb_sst_info::init(const rocksdb::DB* const db)
// Scan through the files in the directory
const struct fileinfo *file_info = dir_info->dir_entry;
for (uint ii= 0; ii < dir_info->number_off_files; ii++, file_info++)
{
for (uint ii = 0; ii < dir_info->number_off_files; ii++, file_info++) {
// find any files ending with m_suffix ...
const std::string name = file_info->name;
const size_t pos = name.find(m_suffix);
if (pos != std::string::npos && name.size() - pos == m_suffix.size())
{
if (pos != std::string::npos && name.size() - pos == m_suffix.size()) {
// ... and remove them
const std::string fullname = path + name;
my_delete(fullname.c_str(), MYF(0));

View File

@@ -47,8 +47,7 @@ class Rdb_sst_file {
std::string generateKey(const std::string &key);
public:
Rdb_sst_file(rocksdb::DB* const db,
rocksdb::ColumnFamilyHandle* const cf,
Rdb_sst_file(rocksdb::DB *const db, rocksdb::ColumnFamilyHandle *const cf,
const rocksdb::DBOptions &db_options, const std::string &name,
const bool tracing);
~Rdb_sst_file();

View File

@@ -24,52 +24,58 @@
namespace myrocks {
void* Rdb_thread::thread_func(void* const thread_ptr)
{
void *Rdb_thread::thread_func(void *const thread_ptr) {
DBUG_ASSERT(thread_ptr != nullptr);
Rdb_thread *const thread = static_cast<Rdb_thread *const>(thread_ptr);
if (!thread->m_run_once.exchange(true))
{
if (!thread->m_run_once.exchange(true)) {
thread->run();
thread->uninit();
}
return nullptr;
}
void Rdb_thread::init(
#ifdef HAVE_PSI_INTERFACE
my_core::PSI_mutex_key stop_bg_psi_mutex_key,
my_core::PSI_cond_key stop_bg_psi_cond_key
#endif
)
{
) {
DBUG_ASSERT(!m_run_once);
mysql_mutex_init(stop_bg_psi_mutex_key, &m_signal_mutex, MY_MUTEX_INIT_FAST);
mysql_cond_init(stop_bg_psi_cond_key, &m_signal_cond, nullptr);
}
void Rdb_thread::uninit()
{
void Rdb_thread::uninit() {
mysql_mutex_destroy(&m_signal_mutex);
mysql_cond_destroy(&m_signal_cond);
}
int Rdb_thread::create_thread(
int Rdb_thread::create_thread(const std::string &thread_name
#ifdef HAVE_PSI_INTERFACE
,
PSI_thread_key background_psi_thread_key
#endif
)
{
return mysql_thread_create(background_psi_thread_key,
&m_handle, nullptr, thread_func, this);
) {
DBUG_ASSERT(!thread_name.empty());
int err = mysql_thread_create(background_psi_thread_key, &m_handle, nullptr,
thread_func, this);
if (!err) {
/*
mysql_thread_create() ends up doing some work underneath and setting the
thread name as "my-func". This isn't what we want. Our intent is to name
the threads according to their purpose so that when displayed under the
debugger then they'll be more easily identifiable. Therefore we'll reset
the name if thread was successfully created.
*/
err = pthread_setname_np(m_handle, thread_name.c_str());
}
return err;
}
void Rdb_thread::signal(const bool &stop_thread)
{
void Rdb_thread::signal(const bool &stop_thread) {
mysql_mutex_lock(&m_signal_mutex);
if (stop_thread) {
m_stop = true;

View File

@@ -16,6 +16,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#pragma once
/* C++ standard header files */
#include <string>
/* MySQL includes */
#include "./my_global.h"
#include <mysql/psi/mysql_table.h>
@@ -26,8 +29,7 @@
namespace myrocks {
class Rdb_thread
{
class Rdb_thread {
private:
// Disable Copying
Rdb_thread(const Rdb_thread &);
@@ -49,21 +51,18 @@ class Rdb_thread
#ifdef HAVE_PSI_INTERFACE
void init(my_core::PSI_mutex_key stop_bg_psi_mutex_key,
my_core::PSI_cond_key stop_bg_psi_cond_key);
int create_thread(
int create_thread(const std::string &thread_name,
my_core::PSI_thread_key background_psi_thread_key);
#else
void init();
int create_thread();
int create_thread(const std::string &thread_name);
#endif
virtual void run(void) = 0;
void signal(const bool &stop_thread = false);
int join()
{
return pthread_join(m_handle, nullptr);
}
int join() { return pthread_join(m_handle, nullptr); }
void uninit();
@@ -73,20 +72,17 @@ class Rdb_thread
static void *thread_func(void *const thread_ptr);
};
/**
MyRocks background thread control
N.B. This is on top of RocksDB's own background threads
(@see rocksdb::CancelAllBackgroundWork())
*/
class Rdb_background_thread : public Rdb_thread
{
class Rdb_background_thread : public Rdb_thread {
private:
bool m_save_stats = false;
void reset()
{
void reset() {
mysql_mutex_assert_owner(&m_signal_mutex);
m_stop = false;
m_save_stats = false;
@@ -95,21 +91,18 @@ class Rdb_background_thread : public Rdb_thread
public:
virtual void run() override;
void request_save_stats()
{
void request_save_stats() {
mysql_mutex_lock(&m_signal_mutex);
m_save_stats = true;
mysql_mutex_unlock(&m_signal_mutex);
}
};
/*
Drop index thread control
*/
struct Rdb_drop_index_thread : public Rdb_thread
{
struct Rdb_drop_index_thread : public Rdb_thread {
virtual void run() override;
};

View File

@@ -33,13 +33,11 @@ namespace myrocks {
Skip past any spaces in the input
*/
const char *rdb_skip_spaces(const struct charset_info_st *const cs,
const char *str)
{
const char *str) {
DBUG_ASSERT(cs != nullptr);
DBUG_ASSERT(str != nullptr);
while (my_isspace(cs, *str))
{
while (my_isspace(cs, *str)) {
str++;
}
@@ -51,18 +49,15 @@ const char* rdb_skip_spaces(const struct charset_info_st* const cs,
Note that str1 can be longer but we only compare up to the number
of characters in str2.
*/
bool rdb_compare_strings_ic(const char* const str1, const char* const str2)
{
bool rdb_compare_strings_ic(const char *const str1, const char *const str2) {
DBUG_ASSERT(str1 != nullptr);
DBUG_ASSERT(str2 != nullptr);
// Scan through the strings
size_t ii;
for (ii = 0; str2[ii]; ii++)
{
for (ii = 0; str2[ii]; ii++) {
if (toupper(static_cast<int>(str1[ii])) !=
toupper(static_cast<int>(str2[ii])))
{
toupper(static_cast<int>(str2[ii]))) {
return false;
}
}
@@ -75,8 +70,7 @@ bool rdb_compare_strings_ic(const char* const str1, const char* const str2)
and skipping all data enclosed in quotes.
*/
const char *rdb_find_in_string(const char *str, const char *pattern,
bool * const succeeded)
{
bool *const succeeded) {
char quote = '\0';
bool escape = false;
@@ -86,38 +80,30 @@ const char* rdb_find_in_string(const char *str, const char *pattern,
*succeeded = false;
for ( ; *str; str++)
{
for (; *str; str++) {
/* If we found a our starting quote character */
if (*str == quote)
{
if (*str == quote) {
/* If it was escaped ignore it */
if (escape)
{
if (escape) {
escape = false;
}
/* Otherwise we are now outside of the quoted string */
else
{
else {
quote = '\0';
}
}
/* Else if we are currently inside a quoted string? */
else if (quote != '\0')
{
else if (quote != '\0') {
/* If so, check for the escape character */
escape = !escape && *str == '\\';
}
/* Else if we found a quote we are starting a quoted string */
else if (*str == '"' || *str == '\'' || *str == '`')
{
else if (*str == '"' || *str == '\'' || *str == '`') {
quote = *str;
}
/* Else we are outside of a quoted string - look for our pattern */
else
{
if (rdb_compare_strings_ic(str, pattern))
{
else {
if (rdb_compare_strings_ic(str, pattern)) {
*succeeded = true;
return str;
}
@@ -134,8 +120,7 @@ const char* rdb_find_in_string(const char *str, const char *pattern,
*/
const char *rdb_check_next_token(const struct charset_info_st *const cs,
const char *str, const char *const pattern,
bool* const succeeded)
{
bool *const succeeded) {
DBUG_ASSERT(cs != nullptr);
DBUG_ASSERT(str != nullptr);
DBUG_ASSERT(pattern != nullptr);
@@ -145,8 +130,7 @@ const char* rdb_check_next_token(const struct charset_info_st* const cs,
str = rdb_skip_spaces(cs, str);
// See if the next characters match the pattern
if (rdb_compare_strings_ic(str, pattern))
{
if (rdb_compare_strings_ic(str, pattern)) {
*succeeded = true;
return str + strlen(pattern);
}
@@ -159,42 +143,34 @@ const char* rdb_check_next_token(const struct charset_info_st* const cs,
Parse id
*/
const char *rdb_parse_id(const struct charset_info_st *const cs,
const char *str, std::string * const id)
{
const char *str, std::string *const id) {
DBUG_ASSERT(cs != nullptr);
DBUG_ASSERT(str != nullptr);
// Move past any spaces
str = rdb_skip_spaces(cs, str);
if (*str == '\0')
{
if (*str == '\0') {
return str;
}
char quote = '\0';
if (*str == '`' || *str == '"')
{
if (*str == '`' || *str == '"') {
quote = *str++;
}
size_t len = 0;
const char *start = str;
if (quote != '\0')
{
for ( ; ; )
{
if (*str == '\0')
{
if (quote != '\0') {
for (;;) {
if (*str == '\0') {
return str;
}
if (*str == quote)
{
if (*str == quote) {
str++;
if (*str != quote)
{
if (*str != quote) {
break;
}
}
@@ -202,27 +178,21 @@ const char* rdb_parse_id(const struct charset_info_st* const cs,
str++;
len++;
}
}
else
{
while (!my_isspace(cs, *str) && *str != '(' && *str != ')' &&
*str != '.' && *str != ',' && *str != '\0')
{
} else {
while (!my_isspace(cs, *str) && *str != '(' && *str != ')' && *str != '.' &&
*str != ',' && *str != '\0') {
str++;
len++;
}
}
// If the user requested the id create it and return it
if (id != nullptr)
{
if (id != nullptr) {
*id = std::string("");
id->reserve(len);
while (len--)
{
while (len--) {
*id += *start;
if (*start++ == quote)
{
if (*start++ == quote) {
start++;
}
}
@@ -234,8 +204,8 @@ const char* rdb_parse_id(const struct charset_info_st* const cs,
/*
Skip id
*/
const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
{
const char *rdb_skip_id(const struct charset_info_st *const cs,
const char *str) {
DBUG_ASSERT(cs != nullptr);
DBUG_ASSERT(str != nullptr);
@@ -243,19 +213,16 @@ const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
}
static const std::size_t rdb_hex_bytes_per_char = 2;
static const std::array<char, 16> rdb_hexdigit =
{
{ '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }
};
static const std::array<char, 16> rdb_hexdigit = {{'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b',
'c', 'd', 'e', 'f'}};
/*
Convert data into a hex string with optional maximum length.
If the data is larger than the maximum length trancate it and append "..".
*/
std::string rdb_hexdump(const char *data, const std::size_t data_len,
const std::size_t maxsize)
{
const std::size_t maxsize) {
DBUG_ASSERT(data != nullptr);
// Count the elements in the string
@@ -264,8 +231,7 @@ std::string rdb_hexdump(const char *data, const std::size_t data_len,
std::size_t len = elems * rdb_hex_bytes_per_char;
std::string str;
if (maxsize != 0 && len > maxsize)
{
if (maxsize != 0 && len > maxsize) {
// If the amount of output is too large adjust the settings
// and leave room for the ".." at the end
elems = (maxsize - 2) / rdb_hex_bytes_per_char;
@@ -276,34 +242,29 @@ std::string rdb_hexdump(const char *data, const std::size_t data_len,
str.reserve(len);
// Loop through the input data and build the output string
for (std::size_t ii = 0; ii < elems; ii++, data++)
{
for (std::size_t ii = 0; ii < elems; ii++, data++) {
uint8_t ch = (uint8_t)*data;
str += rdb_hexdigit[ch >> 4];
str += rdb_hexdigit[ch & 0x0F];
}
// If we can't fit it all add the ".."
if (elems != data_len)
{
if (elems != data_len) {
str += "..";
}
return str;
}
/*
Attempt to access the database subdirectory to see if it exists
*/
bool rdb_database_exists(const std::string& db_name)
{
const std::string dir = std::string(mysql_real_data_home) + FN_DIRSEP
+ db_name;
struct st_my_dir* const dir_info = my_dir(dir.c_str(),
MYF(MY_DONT_SORT | MY_WANT_STAT));
if (dir_info == nullptr)
{
bool rdb_database_exists(const std::string &db_name) {
const std::string dir =
std::string(mysql_real_data_home) + FN_DIRSEP + db_name;
struct st_my_dir *const dir_info =
my_dir(dir.c_str(), MYF(MY_DONT_SORT | MY_WANT_STAT));
if (dir_info == nullptr) {
return false;
}

View File

@@ -101,6 +101,34 @@ namespace myrocks {
DBUG_ASSERT(static_cast<bool>(a) == static_cast<bool>(b))
#endif
/*
Intent behind this macro is to avoid manually typing the function name every
time we want to add the debugging statement and use the compiler for this
work. This avoids typical refactoring problems when one renames a function,
but the tracing message doesn't get updated.
We could use __func__ or __FUNCTION__ macros, but __PRETTY_FUNCTION__
contains the signature of the function as well as its bare name and provides
therefore more context when interpreting the logs.
*/
#define DBUG_ENTER_FUNC() DBUG_ENTER(__PRETTY_FUNCTION__)
/*
Error handling pattern used across MySQL abides by the following rules: "All
functions that can report an error (usually an allocation error), should
return 0/FALSE/false on success, 1/TRUE/true on failure."
https://dev.mysql.com/doc/internals/en/additional-suggestions.html has more
details.
To increase the comprehension and readability of MyRocks codebase we'll use
constants similar to ones from C standard (EXIT_SUCCESS and EXIT_FAILURE) to
make sure that both failure and success paths are clearly identifiable. The
definitions of FALSE and TRUE come from <my_global.h>.
*/
#define HA_EXIT_SUCCESS FALSE
#define HA_EXIT_FAILURE TRUE
/*
Generic constant.
*/
@@ -110,8 +138,7 @@ const size_t RDB_MAX_HEXDUMP_LEN= 1000;
Helper function to get an NULL terminated uchar* out of a given MySQL String.
*/
inline uchar* rdb_mysql_str_to_uchar_str(my_core::String *str)
{
inline uchar *rdb_mysql_str_to_uchar_str(my_core::String *str) {
DBUG_ASSERT(str != nullptr);
return reinterpret_cast<uchar *>(str->c_ptr());
}
@@ -121,8 +148,7 @@ inline uchar* rdb_mysql_str_to_uchar_str(my_core::String *str)
given STL string.
*/
inline const uchar* rdb_std_str_to_uchar_ptr(const std::string &str)
{
inline const uchar *rdb_std_str_to_uchar_ptr(const std::string &str) {
return reinterpret_cast<const uchar *>(str.data());
}
@@ -130,8 +156,7 @@ inline const uchar* rdb_std_str_to_uchar_ptr(const std::string &str)
Helper function to convert seconds to milliseconds.
*/
constexpr int rdb_convert_sec_to_ms(int sec)
{
constexpr int rdb_convert_sec_to_ms(int sec) {
return std::chrono::milliseconds(std::chrono::seconds(sec)).count();
}
@@ -140,8 +165,7 @@ constexpr int rdb_convert_sec_to_ms(int sec)
given RocksDB item.
*/
inline const uchar* rdb_slice_to_uchar_ptr(const rocksdb::Slice *item)
{
inline const uchar *rdb_slice_to_uchar_ptr(const rocksdb::Slice *item) {
DBUG_ASSERT(item != nullptr);
return reinterpret_cast<const uchar *>(item->data());
}
@@ -152,8 +176,7 @@ inline const uchar* rdb_slice_to_uchar_ptr(const rocksdb::Slice *item)
scenario for cases where it has been verified that this intervention has
noticeable benefits.
*/
inline int purge_all_jemalloc_arenas()
{
inline int purge_all_jemalloc_arenas() {
#ifdef HAVE_JEMALLOC
unsigned narenas = 0;
size_t sz = sizeof(unsigned);
@@ -186,26 +209,26 @@ inline int purge_all_jemalloc_arenas()
const char *rdb_skip_spaces(const struct charset_info_st *const cs,
const char *str)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
bool rdb_compare_strings_ic(const char *const str1, const char *const str2)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
const char *rdb_find_in_string(const char *str, const char *pattern,
bool *const succeeded)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
const char *rdb_check_next_token(const struct charset_info_st *const cs,
const char *str, const char *const pattern,
bool *const succeeded)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
const char *rdb_parse_id(const struct charset_info_st *const cs,
const char *str, std::string *const id)
__attribute__((__nonnull__(1, 2), __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__(1, 2), __warn_unused_result__));
const char *rdb_skip_id(const struct charset_info_st *const cs, const char *str)
__attribute__((__nonnull__, __warn_unused_result__));
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
/*
Helper functions to populate strings.
@@ -213,7 +236,7 @@ const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
std::string rdb_hexdump(const char *data, const std::size_t data_len,
const std::size_t maxsize = 0)
__attribute__((__nonnull__));
MY_ATTRIBUTE((__nonnull__));
/*
Helper function to see if a database exists