mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Copy of
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:
@@ -22,8 +22,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/* MySQL includes */
|
/* MySQL includes */
|
||||||
#include <mysql/plugin.h>
|
|
||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
|
#include <mysql/plugin.h>
|
||||||
|
|
||||||
/* MyRocks includes */
|
/* MyRocks includes */
|
||||||
#include "./ha_rocksdb.h"
|
#include "./ha_rocksdb.h"
|
||||||
@@ -33,10 +33,8 @@
|
|||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
static std::vector<Rdb_index_stats>
|
static std::vector<Rdb_index_stats>
|
||||||
extract_index_stats(
|
extract_index_stats(const std::vector<std::string> &files,
|
||||||
const std::vector<std::string>& files,
|
const rocksdb::TablePropertiesCollection &props) {
|
||||||
const rocksdb::TablePropertiesCollection& props
|
|
||||||
) {
|
|
||||||
std::vector<Rdb_index_stats> ret;
|
std::vector<Rdb_index_stats> ret;
|
||||||
for (auto fn : files) {
|
for (auto fn : files) {
|
||||||
const auto it = props.find(fn);
|
const auto it = props.find(fn);
|
||||||
@@ -49,8 +47,7 @@ extract_index_stats(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_event_listener::update_index_stats(
|
void Rdb_event_listener::update_index_stats(
|
||||||
const rocksdb::TableProperties& props
|
const rocksdb::TableProperties &props) {
|
||||||
) {
|
|
||||||
DBUG_ASSERT(m_ddl_manager != nullptr);
|
DBUG_ASSERT(m_ddl_manager != nullptr);
|
||||||
const auto tbl_props =
|
const auto tbl_props =
|
||||||
std::make_shared<const rocksdb::TableProperties>(props);
|
std::make_shared<const rocksdb::TableProperties>(props);
|
||||||
@@ -62,9 +59,7 @@ void Rdb_event_listener::update_index_stats(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_event_listener::OnCompactionCompleted(
|
void Rdb_event_listener::OnCompactionCompleted(
|
||||||
rocksdb::DB *db,
|
rocksdb::DB *db, const rocksdb::CompactionJobInfo &ci) {
|
||||||
const rocksdb::CompactionJobInfo& ci
|
|
||||||
) {
|
|
||||||
DBUG_ASSERT(db != nullptr);
|
DBUG_ASSERT(db != nullptr);
|
||||||
DBUG_ASSERT(m_ddl_manager != nullptr);
|
DBUG_ASSERT(m_ddl_manager != nullptr);
|
||||||
|
|
||||||
@@ -76,17 +71,13 @@ void Rdb_event_listener::OnCompactionCompleted(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_event_listener::OnFlushCompleted(
|
void Rdb_event_listener::OnFlushCompleted(
|
||||||
rocksdb::DB* db,
|
rocksdb::DB *db, const rocksdb::FlushJobInfo &flush_job_info) {
|
||||||
const rocksdb::FlushJobInfo& flush_job_info
|
|
||||||
) {
|
|
||||||
DBUG_ASSERT(db != nullptr);
|
DBUG_ASSERT(db != nullptr);
|
||||||
update_index_stats(flush_job_info.table_properties);
|
update_index_stats(flush_job_info.table_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_event_listener::OnExternalFileIngested(
|
void Rdb_event_listener::OnExternalFileIngested(
|
||||||
rocksdb::DB* db,
|
rocksdb::DB *db, const rocksdb::ExternalFileIngestionInfo &info) {
|
||||||
const rocksdb::ExternalFileIngestionInfo& info
|
|
||||||
) {
|
|
||||||
DBUG_ASSERT(db != nullptr);
|
DBUG_ASSERT(db != nullptr);
|
||||||
update_index_stats(info.table_properties);
|
update_index_stats(info.table_properties);
|
||||||
}
|
}
|
||||||
|
@@ -21,29 +21,26 @@ namespace myrocks {
|
|||||||
|
|
||||||
class Rdb_ddl_manager;
|
class Rdb_ddl_manager;
|
||||||
|
|
||||||
class Rdb_event_listener : public rocksdb::EventListener
|
class Rdb_event_listener : public rocksdb::EventListener {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_event_listener(const Rdb_event_listener &) = delete;
|
Rdb_event_listener(const Rdb_event_listener &) = delete;
|
||||||
Rdb_event_listener &operator=(const Rdb_event_listener &) = delete;
|
Rdb_event_listener &operator=(const Rdb_event_listener &) = delete;
|
||||||
|
|
||||||
explicit Rdb_event_listener(Rdb_ddl_manager* const ddl_manager) :
|
explicit Rdb_event_listener(Rdb_ddl_manager *const ddl_manager)
|
||||||
m_ddl_manager(ddl_manager) {
|
: m_ddl_manager(ddl_manager) {}
|
||||||
}
|
|
||||||
|
|
||||||
void OnCompactionCompleted(
|
void OnCompactionCompleted(rocksdb::DB *db,
|
||||||
rocksdb::DB* db, const rocksdb::CompactionJobInfo& ci) override;
|
const rocksdb::CompactionJobInfo &ci) override;
|
||||||
void OnFlushCompleted(
|
void OnFlushCompleted(rocksdb::DB *db,
|
||||||
rocksdb::DB* db, const rocksdb::FlushJobInfo& flush_job_info) override;
|
const rocksdb::FlushJobInfo &flush_job_info) override;
|
||||||
void OnExternalFileIngested(
|
void OnExternalFileIngested(
|
||||||
rocksdb::DB* db, const rocksdb::ExternalFileIngestionInfo& ingestion_info)
|
rocksdb::DB *db,
|
||||||
override;
|
const rocksdb::ExternalFileIngestionInfo &ingestion_info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Rdb_ddl_manager *m_ddl_manager;
|
Rdb_ddl_manager *m_ddl_manager;
|
||||||
|
|
||||||
void update_index_stats(
|
void update_index_stats(const rocksdb::TableProperties &props);
|
||||||
const rocksdb::TableProperties& props);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace myrocks
|
} // namespace myrocks
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -111,6 +111,16 @@ const char * const HIDDEN_PK_NAME= "HIDDEN_PK_ID";
|
|||||||
*/
|
*/
|
||||||
const char *const PER_INDEX_CF_NAME = "$per_index_cf";
|
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
|
Default, minimal valid, and maximum valid sampling rate values when collecting
|
||||||
statistics about table.
|
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_TOO_MANY_LOCKS (HA_ERR_LAST + 3)
|
||||||
#define HA_ERR_ROCKSDB_LAST HA_ERR_ROCKSDB_TOO_MANY_LOCKS
|
#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));
|
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 ?
|
//TODO: join this with Rdb_tbl_def ?
|
||||||
*/
|
*/
|
||||||
struct Rdb_table_handler
|
struct Rdb_table_handler {
|
||||||
{
|
|
||||||
char *m_table_name;
|
char *m_table_name;
|
||||||
uint m_table_name_length;
|
uint m_table_name_length;
|
||||||
int m_ref_count;
|
int m_ref_count;
|
||||||
@@ -209,8 +217,6 @@ struct Rdb_table_handler
|
|||||||
Rdb_atomic_perf_counters m_table_perf_context;
|
Rdb_atomic_perf_counters m_table_perf_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Rdb_key_def;
|
class Rdb_key_def;
|
||||||
class Rdb_tbl_def;
|
class Rdb_tbl_def;
|
||||||
class Rdb_transaction;
|
class Rdb_transaction;
|
||||||
@@ -223,31 +229,25 @@ const char *const rocksdb_hton_name= "ROCKSDB";
|
|||||||
typedef struct _gl_index_id_s {
|
typedef struct _gl_index_id_s {
|
||||||
uint32_t cf_id;
|
uint32_t cf_id;
|
||||||
uint32_t index_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;
|
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;
|
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 ||
|
return cf_id < other.cf_id ||
|
||||||
(cf_id == other.cf_id && index_id < other.index_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 ||
|
return cf_id < other.cf_id ||
|
||||||
(cf_id == other.cf_id && index_id <= other.index_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 ||
|
return cf_id > other.cf_id ||
|
||||||
(cf_id == other.cf_id && index_id > other.index_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 ||
|
return cf_id > other.cf_id ||
|
||||||
(cf_id == other.cf_id && index_id >= other.index_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 */
|
/* Provide hash function for GL_INDEX_ID so we can include it in sets */
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <> struct hash<myrocks::GL_INDEX_ID> {
|
||||||
struct hash<myrocks::GL_INDEX_ID>
|
std::size_t operator()(const myrocks::GL_INDEX_ID &gl_index_id) const {
|
||||||
{
|
const uint64_t val =
|
||||||
std::size_t operator()(const myrocks::GL_INDEX_ID& gl_index_id) const
|
((uint64_t)gl_index_id.cf_id << 32 | (uint64_t)gl_index_id.index_id);
|
||||||
{
|
|
||||||
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);
|
return std::hash<uint64_t>()(val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -314,8 +311,7 @@ namespace myrocks {
|
|||||||
Class definition for ROCKSDB storage engine plugin handler
|
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
|
my_core::THR_LOCK_DATA m_db_lock; ///< MySQL database lock
|
||||||
|
|
||||||
Rdb_table_handler *m_table_handler; ///< Open table handler
|
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;
|
uchar *m_sk_packed_tuple_old;
|
||||||
Rdb_string_writer m_sk_tails_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
|
Temporary space for packing VARCHARs (we provide it to
|
||||||
pack_record()/pack_index_tuple() calls).
|
pack_record()/pack_index_tuple() calls).
|
||||||
@@ -452,36 +452,33 @@ class ha_rocksdb: public my_core::handler
|
|||||||
Rdb_tbl_def *const tbl_def_arg,
|
Rdb_tbl_def *const tbl_def_arg,
|
||||||
const TABLE *const old_table_arg = nullptr,
|
const TABLE *const old_table_arg = nullptr,
|
||||||
const Rdb_tbl_def *const old_tbl_def_arg = nullptr) const
|
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)
|
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_iterator_for_rnd_scan();
|
||||||
void setup_scan_iterator(const Rdb_key_def &kd, rocksdb::Slice *const slice)
|
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);
|
setup_scan_iterator(kd, slice, false, false, 0);
|
||||||
}
|
}
|
||||||
bool is_ascending(const Rdb_key_def &keydef,
|
bool is_ascending(const Rdb_key_def &keydef,
|
||||||
enum ha_rkey_function find_flag) const
|
enum ha_rkey_function find_flag) const
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
void setup_scan_iterator(const Rdb_key_def& kd,
|
void setup_scan_iterator(const Rdb_key_def &kd, rocksdb::Slice *slice,
|
||||||
rocksdb::Slice *slice, const bool use_all_keys,
|
const bool use_all_keys, const bool is_ascending,
|
||||||
const bool is_ascending, const uint eq_cond_len)
|
const uint eq_cond_len) MY_ATTRIBUTE((__nonnull__));
|
||||||
__attribute__((__nonnull__));
|
|
||||||
void release_scan_iterator(void);
|
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,
|
rocksdb::ColumnFamilyHandle *const column_family,
|
||||||
const rocksdb::Slice& key,
|
const rocksdb::Slice &key, std::string *const value) const;
|
||||||
std::string* const value) const;
|
|
||||||
|
|
||||||
int get_row_by_rowid(uchar *const buf, const char *const rowid,
|
int get_row_by_rowid(uchar *const buf, const char *const rowid,
|
||||||
const uint rowid_size)
|
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,
|
int get_row_by_rowid(uchar *const buf, const uchar *const rowid,
|
||||||
const uint rowid_size)
|
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),
|
return get_row_by_rowid(buf, reinterpret_cast<const char *>(rowid),
|
||||||
rowid_size);
|
rowid_size);
|
||||||
}
|
}
|
||||||
@@ -489,18 +486,18 @@ class ha_rocksdb: public my_core::handler
|
|||||||
void update_auto_incr_val();
|
void update_auto_incr_val();
|
||||||
void load_auto_incr_value();
|
void load_auto_incr_value();
|
||||||
longlong update_hidden_pk_val();
|
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)
|
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
|
bool can_use_single_delete(const uint &index) const
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
bool skip_unique_check() const __attribute__((__warn_unused_result__));
|
bool skip_unique_check() const MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
void set_force_skip_unique_check(bool skip) override;
|
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)
|
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
|
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);
|
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;
|
Rdb_field_encoder *m_encoder_arr;
|
||||||
|
|
||||||
/* Describes instructions on how to decode the field */
|
/* Describes instructions on how to decode the field */
|
||||||
class READ_FIELD
|
class READ_FIELD {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/* Points to Rdb_field_encoder describing the field */
|
/* Points to Rdb_field_encoder describing the field */
|
||||||
Rdb_field_encoder *m_field_enc;
|
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 get_storage_type(Rdb_field_encoder *const encoder, const uint &kp);
|
||||||
void setup_field_converters();
|
void setup_field_converters();
|
||||||
int alloc_key_buffers(const TABLE *const table_arg,
|
int alloc_key_buffers(const TABLE *const table_arg,
|
||||||
const Rdb_tbl_def* const tbl_def_arg)
|
const Rdb_tbl_def *const tbl_def_arg,
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
bool alloc_alter_buffers = false)
|
||||||
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
void free_key_buffers();
|
void free_key_buffers();
|
||||||
|
|
||||||
// the buffer size should be at least 2*Rdb_key_def::INDEX_NUMBER_SIZE
|
// 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:
|
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.
|
at the start of each query.
|
||||||
*/
|
*/
|
||||||
bool m_store_row_debug_checksums;
|
bool m_store_row_debug_checksums;
|
||||||
@@ -579,9 +577,8 @@ public:
|
|||||||
|
|
||||||
ha_rocksdb(my_core::handlerton *const hton,
|
ha_rocksdb(my_core::handlerton *const hton,
|
||||||
my_core::TABLE_SHARE *const table_arg);
|
my_core::TABLE_SHARE *const table_arg);
|
||||||
~ha_rocksdb()
|
~ha_rocksdb() {
|
||||||
{
|
int err MY_ATTRIBUTE((__unused__));
|
||||||
int err __attribute__((__unused__));
|
|
||||||
err = finalize_bulk_load();
|
err = finalize_bulk_load();
|
||||||
DBUG_ASSERT(err == 0);
|
DBUG_ASSERT(err == 0);
|
||||||
mysql_mutex_destroy(&m_bulk_load_mutex);
|
mysql_mutex_destroy(&m_bulk_load_mutex);
|
||||||
@@ -590,15 +587,23 @@ public:
|
|||||||
/** @brief
|
/** @brief
|
||||||
The name that will be used for display purposes.
|
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: */
|
/* 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
|
/** @brief
|
||||||
The file extensions.
|
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
|
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
|
This is a list of flags that indicate what functionality the storage engine
|
||||||
implements. The current table flags are documented in handler.h
|
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
|
HA_BINLOG_STMT_CAPABLE
|
||||||
We are saying that this engine is just statement capable to have
|
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
|
If we don't set it, filesort crashes, because it assumes rowids are
|
||||||
1..8 byte numbers
|
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 |
|
HA_REC_NOT_IN_SEQ | HA_CAN_INDEX_BLOBS |
|
||||||
(m_pk_can_be_decoded ? HA_PRIMARY_KEY_IN_READ_INDEX : 0) |
|
(m_pk_can_be_decoded ? HA_PRIMARY_KEY_IN_READ_INDEX : 0) |
|
||||||
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
|
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_NULL_IN_KEY |
|
||||||
HA_NULL_IN_KEY |
|
HA_PARTIAL_COLUMN_READ);
|
||||||
HA_PARTIAL_COLUMN_READ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init_with_fields() override;
|
bool init_with_fields() override;
|
||||||
@@ -641,61 +646,62 @@ public:
|
|||||||
If all_parts is set, MySQL wants to know the flags for the combined
|
If all_parts is set, MySQL wants to know the flags for the combined
|
||||||
index, up to and including 'part'.
|
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()
|
const key_map *keys_to_use_for_scanning() override {
|
||||||
{
|
DBUG_ENTER_FUNC();
|
||||||
return &key_map_full;
|
|
||||||
|
DBUG_RETURN(&key_map_full);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool primary_key_is_clustered()
|
bool primary_key_is_clustered() override {
|
||||||
{
|
DBUG_ENTER_FUNC();
|
||||||
return true;
|
|
||||||
|
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);
|
return m_store_row_debug_checksums && (rand() % 100 < m_checksums_pct);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rename_table(const char* const from, const char* const to)
|
int rename_table(const char *const from, const char *const to) override
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
int convert_record_from_storage_format(const rocksdb::Slice *const key,
|
int convert_record_from_storage_format(const rocksdb::Slice *const key,
|
||||||
const rocksdb::Slice *const value,
|
const rocksdb::Slice *const value,
|
||||||
uchar *const buf)
|
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,
|
int convert_record_from_storage_format(const rocksdb::Slice *const key,
|
||||||
uchar *const buf)
|
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,
|
void convert_record_to_storage_format(const rocksdb::Slice &pk_packed_slice,
|
||||||
Rdb_string_writer *const pk_unpack_info,
|
Rdb_string_writer *const pk_unpack_info,
|
||||||
rocksdb::Slice *const packed_rec)
|
rocksdb::Slice *const packed_rec)
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
static const char *get_key_name(const uint index,
|
static const char *get_key_name(const uint index,
|
||||||
const TABLE *const table_arg,
|
const TABLE *const table_arg,
|
||||||
const Rdb_tbl_def *const tbl_def_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,
|
static const char *get_key_comment(const uint index,
|
||||||
const TABLE *const table_arg,
|
const TABLE *const table_arg,
|
||||||
const Rdb_tbl_def *const tbl_def_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,
|
static bool is_hidden_pk(const uint index, const TABLE *const table_arg,
|
||||||
const Rdb_tbl_def *const tbl_def_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,
|
static uint pk_index(const TABLE *const table_arg,
|
||||||
const Rdb_tbl_def *const tbl_def_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,
|
static bool is_pk(const uint index, const TABLE *table_arg,
|
||||||
const Rdb_tbl_def *tbl_def_arg)
|
const Rdb_tbl_def *tbl_def_arg)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
/** @brief
|
/** @brief
|
||||||
unireg.cc will call max_supported_record_length(), max_supported_keys(),
|
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
|
send. Return *real* limits of your storage engine here; MySQL will do
|
||||||
min(your_limits, MySQL_limits) automatically.
|
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
|
/** @brief
|
||||||
unireg.cc will call this to make sure that the storage engine can handle
|
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
|
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
|
There is no need to implement ..._key_... methods if your engine doesn't
|
||||||
support indexes.
|
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.
|
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
|
(e.g. save number of records seen on full table scan and/or use file size
|
||||||
as upper bound)
|
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,
|
int index_read_map(uchar *const buf, const uchar *const key,
|
||||||
key_part_map keypart_map,
|
key_part_map keypart_map,
|
||||||
enum ha_rkey_function find_flag);
|
enum ha_rkey_function find_flag) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
int index_read_map_impl(uchar *const buf, const uchar *const key,
|
int index_read_map_impl(uchar *const buf, const uchar *const key,
|
||||||
key_part_map keypart_map,
|
key_part_map keypart_map,
|
||||||
enum ha_rkey_function find_flag,
|
enum ha_rkey_function find_flag,
|
||||||
const key_range *end_key)
|
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,
|
int index_read_last_map(uchar *const buf, const uchar *const key,
|
||||||
key_part_map keypart_map)
|
key_part_map keypart_map) override
|
||||||
__attribute__((__warn_unused_result__));;
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
int read_range_first(const key_range *const start_key,
|
int read_range_first(const key_range *const start_key,
|
||||||
const key_range* const end_key,
|
const key_range *const end_key, bool eq_range,
|
||||||
bool eq_range, bool sorted)
|
bool sorted) override
|
||||||
__attribute__((__warn_unused_result__));;
|
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;
|
virtual double read_time(uint, uint, ha_rows rows) override;
|
||||||
|
|
||||||
int open(const char* const name, int mode, uint test_if_locked)
|
int open(const char *const name, int mode, uint test_if_locked) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int close(void) __attribute__((__warn_unused_result__));
|
int close(void) override MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
int write_row(uchar* const buf) __attribute__((__warn_unused_result__));
|
int write_row(uchar *const buf) override
|
||||||
int update_row(const uchar* const old_data, uchar* const new_data)
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
__attribute__((__warn_unused_result__));
|
int update_row(const uchar *const old_data, uchar *const new_data) override
|
||||||
int delete_row(const uchar* const buf)
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
__attribute__((__warn_unused_result__));
|
int delete_row(const uchar *const buf) override
|
||||||
rocksdb::Status delete_or_singledelete(uint index,
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
Rdb_transaction* const tx,
|
rocksdb::Status delete_or_singledelete(uint index, Rdb_transaction *const tx,
|
||||||
rocksdb::ColumnFamilyHandle *const cf,
|
rocksdb::ColumnFamilyHandle *const cf,
|
||||||
const rocksdb::Slice &key)
|
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)
|
int index_next_with_direction(uchar *const buf, bool move_forward)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int index_prev(uchar* const buf) __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_first(uchar *const buf) override
|
||||||
int index_last(uchar* const buf) __attribute__((__warn_unused_result__));
|
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
|
Default implementation from cancel_pushed_idx_cond() suits us
|
||||||
*/
|
*/
|
||||||
private:
|
private:
|
||||||
struct key_def_cf_info
|
struct key_def_cf_info {
|
||||||
{
|
|
||||||
rocksdb::ColumnFamilyHandle *cf_handle;
|
rocksdb::ColumnFamilyHandle *cf_handle;
|
||||||
bool is_reverse_cf;
|
bool is_reverse_cf;
|
||||||
bool is_auto_cf;
|
bool is_auto_cf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct update_row_info
|
struct update_row_info {
|
||||||
{
|
|
||||||
Rdb_transaction *tx;
|
Rdb_transaction *tx;
|
||||||
const uchar *new_data;
|
const uchar *new_data;
|
||||||
const uchar *old_data;
|
const uchar *old_data;
|
||||||
@@ -801,112 +843,124 @@ private:
|
|||||||
bool skip_unique_check;
|
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,
|
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;
|
std::array<struct key_def_cf_info, MAX_INDEXES + 1> *const cfs)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
const MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
int create_key_def(const TABLE *const table_arg, const uint &i,
|
int create_key_def(const TABLE *const table_arg, const uint &i,
|
||||||
const Rdb_tbl_def *const tbl_def_arg,
|
const Rdb_tbl_def *const tbl_def_arg,
|
||||||
std::shared_ptr<Rdb_key_def> *const new_key_def,
|
std::shared_ptr<Rdb_key_def> *const new_key_def,
|
||||||
const struct key_def_cf_info& cf_info) const;
|
const struct key_def_cf_info &cf_info) const
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
int create_inplace_key_defs(const TABLE* const table_arg,
|
int create_inplace_key_defs(
|
||||||
Rdb_tbl_def* vtbl_def_arg,
|
const TABLE *const table_arg, Rdb_tbl_def *vtbl_def_arg,
|
||||||
const TABLE *const old_table_arg,
|
const TABLE *const old_table_arg,
|
||||||
const Rdb_tbl_def *const old_tbl_def_arg,
|
const Rdb_tbl_def *const old_tbl_def_arg,
|
||||||
const std::array<key_def_cf_info, MAX_INDEXES + 1>& cfs) const;
|
const std::array<key_def_cf_info, MAX_INDEXES + 1> &cfs) const
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
std::unordered_map<std::string, uint> get_old_key_positions(
|
std::unordered_map<std::string, uint>
|
||||||
const TABLE* table_arg,
|
get_old_key_positions(const TABLE *table_arg, const Rdb_tbl_def *tbl_def_arg,
|
||||||
const Rdb_tbl_def* tbl_def_arg,
|
|
||||||
const TABLE *old_table_arg,
|
const TABLE *old_table_arg,
|
||||||
const Rdb_tbl_def *old_tbl_def_arg) const
|
const Rdb_tbl_def *old_tbl_def_arg) const
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
int compare_key_parts(const KEY *const old_key,
|
int compare_key_parts(const KEY *const old_key,
|
||||||
const KEY *const new_key) const;
|
const KEY *const new_key) const;
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
int index_first_intern(uchar *buf)
|
int index_first_intern(uchar *buf)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
int index_last_intern(uchar *buf)
|
int index_last_intern(uchar *buf)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
enum icp_result check_index_cond() const;
|
enum icp_result check_index_cond() const;
|
||||||
int find_icp_matching_index_rec(const bool &move_forward, uchar *const buf)
|
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();
|
void calc_updated_indexes();
|
||||||
int update_write_row(const uchar *const old_data, const uchar *const new_data,
|
int update_write_row(const uchar *const old_data, const uchar *const new_data,
|
||||||
const bool skip_unique_check)
|
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 get_pk_for_update(struct update_row_info *const row_info);
|
||||||
int check_and_lock_unique_pk(const uint &key_id,
|
int check_and_lock_unique_pk(const uint &key_id,
|
||||||
const struct update_row_info &row_info,
|
const struct update_row_info &row_info,
|
||||||
bool *const found, bool *const pk_changed)
|
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,
|
int check_and_lock_sk(const uint &key_id,
|
||||||
const struct update_row_info &row_info,
|
const struct update_row_info &row_info,
|
||||||
bool *const found) const
|
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,
|
int check_uniqueness_and_lock(const struct update_row_info &row_info,
|
||||||
bool *const pk_changed)
|
bool *const pk_changed)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
bool over_bulk_load_threshold(int *err)
|
bool over_bulk_load_threshold(int *err)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int bulk_load_key(Rdb_transaction* const tx,
|
int check_duplicate_sk(const TABLE *table_arg, const Rdb_key_def &index,
|
||||||
const Rdb_key_def& kd,
|
const rocksdb::Slice *key,
|
||||||
const rocksdb::Slice& key,
|
struct unique_sk_buf_info *sk_info)
|
||||||
const rocksdb::Slice& value)
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
int bulk_load_key(Rdb_transaction *const tx, const Rdb_key_def &kd,
|
||||||
int update_pk(const Rdb_key_def& kd,
|
const rocksdb::Slice &key, const rocksdb::Slice &value)
|
||||||
const struct update_row_info& row_info,
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
const bool &pk_changed)
|
int update_pk(const Rdb_key_def &kd, const struct update_row_info &row_info,
|
||||||
__attribute__((__warn_unused_result__));
|
const bool &pk_changed) MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int update_sk(const TABLE* const table_arg,
|
int update_sk(const TABLE *const table_arg, const Rdb_key_def &kd,
|
||||||
const Rdb_key_def& kd,
|
|
||||||
const struct update_row_info &row_info)
|
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,
|
int update_indexes(const struct update_row_info &row_info,
|
||||||
const bool &pk_changed)
|
const bool &pk_changed)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
int read_key_exact(const Rdb_key_def& kd,
|
int read_key_exact(const Rdb_key_def &kd, rocksdb::Iterator *const iter,
|
||||||
rocksdb::Iterator* const iter, const bool &using_full_key,
|
const bool &using_full_key,
|
||||||
const rocksdb::Slice &key_slice) const
|
const rocksdb::Slice &key_slice) const
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
int read_before_key(const Rdb_key_def& kd,
|
int read_before_key(const Rdb_key_def &kd, const bool &using_full_key,
|
||||||
const bool &using_full_key,
|
|
||||||
const rocksdb::Slice &key_slice)
|
const rocksdb::Slice &key_slice)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
int read_after_key(const Rdb_key_def& kd,
|
int read_after_key(const Rdb_key_def &kd, const bool &using_full_key,
|
||||||
const bool &using_full_key,
|
|
||||||
const rocksdb::Slice &key_slice)
|
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,
|
int position_to_correct_key(
|
||||||
const enum ha_rkey_function &find_flag,
|
const Rdb_key_def &kd, const enum ha_rkey_function &find_flag,
|
||||||
const bool &full_key_match,
|
const bool &full_key_match, const uchar *const key,
|
||||||
const uchar* const key,
|
const key_part_map &keypart_map, const rocksdb::Slice &key_slice,
|
||||||
const key_part_map &keypart_map,
|
bool *const move_forward) MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
const rocksdb::Slice& key_slice,
|
|
||||||
bool* const move_forward)
|
|
||||||
__attribute__((__warn_unused_result__));
|
|
||||||
|
|
||||||
int read_row_from_primary_key(uchar *const buf)
|
int read_row_from_primary_key(uchar *const buf)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
int read_row_from_secondary_key(uchar* const buf,
|
int read_row_from_secondary_key(uchar *const buf, const Rdb_key_def &kd,
|
||||||
const Rdb_key_def& kd,
|
|
||||||
bool move_forward)
|
bool move_forward)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_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__));
|
|
||||||
|
|
||||||
int calc_eq_cond_len(const Rdb_key_def &kd,
|
int calc_eq_cond_len(const Rdb_key_def &kd,
|
||||||
const enum ha_rkey_function &find_flag,
|
const enum ha_rkey_function &find_flag,
|
||||||
@@ -914,26 +968,28 @@ private:
|
|||||||
const int &bytes_changed_by_succ,
|
const int &bytes_changed_by_succ,
|
||||||
const key_range *const end_key,
|
const key_range *const end_key,
|
||||||
uint *const end_key_packed_size)
|
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)
|
Rdb_tbl_def *get_table_if_exists(const char *const tablename)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
void read_thd_vars(THD* const thd)
|
void read_thd_vars(THD *const thd) MY_ATTRIBUTE((__nonnull__));
|
||||||
__attribute__((__nonnull__));
|
|
||||||
const char *thd_rocksdb_tmpdir()
|
const char *thd_rocksdb_tmpdir()
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
bool contains_foreign_key(THD *const thd)
|
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,
|
int inplace_populate_sk(
|
||||||
const std::unordered_set<std::shared_ptr<Rdb_key_def>>& indexes);
|
TABLE *const table_arg,
|
||||||
|
const std::unordered_set<std::shared_ptr<Rdb_key_def>> &indexes)
|
||||||
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int index_init(uint idx, bool sorted) __attribute__((__warn_unused_result__));
|
int index_init(uint idx, bool sorted) override
|
||||||
int index_end() __attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
int index_end() override MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
void unlock_row();
|
void unlock_row() override;
|
||||||
|
|
||||||
/** @brief
|
/** @brief
|
||||||
Unlike index_init(), rnd_init() can be called two consecutive times
|
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
|
cursor to the start of the table; no need to deallocate and allocate
|
||||||
it again. This is a required method.
|
it again. This is a required method.
|
||||||
*/
|
*/
|
||||||
int rnd_init(bool scan) __attribute__((__warn_unused_result__));
|
int rnd_init(bool scan) override MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int rnd_end() __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)
|
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)
|
int rnd_pos(uchar *const buf, uchar *const pos) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
void position(const uchar* const record);
|
void position(const uchar *const record) override;
|
||||||
int info(uint) override;
|
int info(uint) override;
|
||||||
|
|
||||||
/* This function will always return success, therefore no annotation related
|
/* This function will always return success, therefore no annotation related
|
||||||
* to checking the return value. Can't change the signature because it's
|
* to checking the return value. Can't change the signature because it's
|
||||||
* required by the interface. */
|
* 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)
|
int start_stmt(THD *const thd, thr_lock_type lock_type) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int external_lock(THD* const thd, int lock_type)
|
int external_lock(THD *const thd, int lock_type) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int delete_all_rows(ha_rows* const nrows) __attribute__((__warn_unused_result__));
|
int truncate() override MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int truncate() __attribute__((__warn_unused_result__));
|
|
||||||
|
int reset() override {
|
||||||
|
DBUG_ENTER_FUNC();
|
||||||
|
|
||||||
int reset() override
|
|
||||||
{
|
|
||||||
/* Free blob data */
|
/* Free blob data */
|
||||||
m_retrieved_record.clear();
|
m_retrieved_record.clear();
|
||||||
return 0;
|
|
||||||
|
DBUG_RETURN(HA_EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int check(THD* const thd, HA_CHECK_OPT* const check_opt)
|
int check(THD *const thd, HA_CHECK_OPT *const check_opt) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
void remove_rows(Rdb_tbl_def *const tbl);
|
void remove_rows(Rdb_tbl_def *const tbl);
|
||||||
ha_rows records_in_range(uint inx, key_range *const min_key,
|
ha_rows records_in_range(uint inx, key_range *const min_key,
|
||||||
key_range* const max_key)
|
key_range *const max_key) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int delete_table(const char* const from) __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,
|
int create(const char *const name, TABLE *const form,
|
||||||
HA_CREATE_INFO* const create_info)
|
HA_CREATE_INFO *const create_info) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
bool check_if_incompatible_data(HA_CREATE_INFO *const info,
|
bool check_if_incompatible_data(HA_CREATE_INFO *const info,
|
||||||
uint table_changes)
|
uint table_changes) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
THR_LOCK_DATA **store_lock(THD *const thd, THR_LOCK_DATA **to,
|
THR_LOCK_DATA **store_lock(THD *const thd, THR_LOCK_DATA **to,
|
||||||
enum thr_lock_type lock_type)
|
enum thr_lock_type lock_type) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
my_bool register_query_cache_table(THD *const thd, char *const table_key,
|
my_bool register_query_cache_table(THD *const thd, char *const table_key,
|
||||||
uint key_length,
|
uint key_length,
|
||||||
qc_engine_callback *const engine_callback,
|
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 */
|
/* Currently, we don't support query cache */
|
||||||
return FALSE;
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_error_message(const int error, String* const buf)
|
bool get_error_message(const int error, String *const buf) override
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
void get_auto_increment(ulonglong offset, ulonglong increment,
|
void get_auto_increment(ulonglong offset, ulonglong increment,
|
||||||
ulonglong nb_desired_values,
|
ulonglong nb_desired_values,
|
||||||
ulonglong *const first_value,
|
ulonglong *const first_value,
|
||||||
ulonglong* const nb_reserved_values);
|
ulonglong *const nb_reserved_values) override;
|
||||||
void update_create_info(HA_CREATE_INFO* const create_info);
|
void update_create_info(HA_CREATE_INFO *const create_info) override;
|
||||||
int optimize(THD* const thd, HA_CHECK_OPT* const check_opt)
|
int optimize(THD *const thd, HA_CHECK_OPT *const check_opt) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int analyze(THD* const thd, HA_CHECK_OPT* const check_opt)
|
int analyze(THD *const thd, HA_CHECK_OPT *const check_opt) override
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
int calculate_stats(const TABLE *const table_arg, THD *const thd,
|
int calculate_stats(const TABLE *const table_arg, THD *const thd,
|
||||||
HA_CHECK_OPT *const check_opt)
|
HA_CHECK_OPT *const check_opt)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
enum_alter_inplace_result check_if_supported_inplace_alter(
|
enum_alter_inplace_result check_if_supported_inplace_alter(
|
||||||
TABLE *altered_table,
|
TABLE *altered_table,
|
||||||
my_core::Alter_inplace_info *const ha_alter_info) override;
|
my_core::Alter_inplace_info *const ha_alter_info) override;
|
||||||
|
|
||||||
bool prepare_inplace_alter_table(TABLE* const altered_table,
|
bool prepare_inplace_alter_table(
|
||||||
my_core::Alter_inplace_info* const ha_alter_info);
|
TABLE *const altered_table,
|
||||||
|
my_core::Alter_inplace_info *const ha_alter_info) override;
|
||||||
|
|
||||||
bool inplace_alter_table(TABLE* const altered_table,
|
bool inplace_alter_table(
|
||||||
my_core::Alter_inplace_info* const ha_alter_info);
|
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,
|
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_use_read_free_rpl(const char *const whitelist);
|
||||||
void set_skip_unique_check_tables(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
|
Helper class for in-place alter, for storing handler context between inplace
|
||||||
alter calls
|
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 */
|
/* The new table definition */
|
||||||
Rdb_tbl_def *const m_new_tdef;
|
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,
|
std::shared_ptr<Rdb_key_def> *new_key_descr, uint old_n_keys,
|
||||||
uint new_n_keys,
|
uint new_n_keys,
|
||||||
std::unordered_set<std::shared_ptr<Rdb_key_def>> added_indexes,
|
std::unordered_set<std::shared_ptr<Rdb_key_def>> added_indexes,
|
||||||
std::unordered_set<GL_INDEX_ID> dropped_index_ids,
|
std::unordered_set<GL_INDEX_ID> dropped_index_ids, uint n_added_keys,
|
||||||
uint n_added_keys, uint n_dropped_keys) :
|
uint n_dropped_keys)
|
||||||
my_core::inplace_alter_handler_ctx(), m_new_tdef(new_tdef),
|
: 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_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_old_n_keys(old_n_keys), m_new_n_keys(new_n_keys),
|
||||||
m_added_indexes(added_indexes),
|
m_added_indexes(added_indexes), m_dropped_index_ids(dropped_index_ids),
|
||||||
m_dropped_index_ids(dropped_index_ids),
|
m_n_added_keys(n_added_keys), m_n_dropped_keys(n_dropped_keys) {}
|
||||||
m_n_added_keys(n_added_keys),
|
|
||||||
m_n_dropped_keys(n_dropped_keys)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Rdb_inplace_alter_ctx() {}
|
~Rdb_inplace_alter_ctx() {}
|
||||||
|
|
||||||
|
@@ -32,27 +32,31 @@ enum RDB_IO_ERROR_TYPE {
|
|||||||
RDB_IO_ERROR_TX_COMMIT,
|
RDB_IO_ERROR_TX_COMMIT,
|
||||||
RDB_IO_ERROR_DICT_COMMIT,
|
RDB_IO_ERROR_DICT_COMMIT,
|
||||||
RDB_IO_ERROR_BG_THREAD,
|
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)
|
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,
|
int rdb_split_normalized_tablename(const std::string &fullname, std::string *db,
|
||||||
std::string *table = nullptr,
|
std::string *table = nullptr,
|
||||||
std::string *partition = nullptr)
|
std::string *partition = nullptr)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
std::vector<std::string> rdb_get_open_table_names(void);
|
std::vector<std::string> rdb_get_open_table_names(void);
|
||||||
|
|
||||||
int rdb_get_table_perf_counters(const char *tablename,
|
int rdb_get_table_perf_counters(const char *tablename,
|
||||||
Rdb_perf_counters *counters)
|
Rdb_perf_counters *counters)
|
||||||
__attribute__((__nonnull__(2)));
|
MY_ATTRIBUTE((__nonnull__(2)));
|
||||||
|
|
||||||
void rdb_get_global_perf_counters(Rdb_perf_counters *counters)
|
void rdb_get_global_perf_counters(Rdb_perf_counters *counters)
|
||||||
__attribute__((__nonnull__(1)));
|
MY_ATTRIBUTE((__nonnull__(1)));
|
||||||
|
|
||||||
void rdb_queue_save_stats_request();
|
void rdb_queue_save_stats_request();
|
||||||
|
|
||||||
@@ -69,14 +73,14 @@ rocksdb::BlockBasedTableOptions& rdb_get_table_options();
|
|||||||
|
|
||||||
class Rdb_dict_manager;
|
class Rdb_dict_manager;
|
||||||
Rdb_dict_manager *rdb_get_dict_manager(void)
|
Rdb_dict_manager *rdb_get_dict_manager(void)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
class Rdb_ddl_manager;
|
class Rdb_ddl_manager;
|
||||||
Rdb_ddl_manager *rdb_get_ddl_manager(void)
|
Rdb_ddl_manager *rdb_get_ddl_manager(void)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
class Rdb_binlog_manager;
|
class Rdb_binlog_manager;
|
||||||
Rdb_binlog_manager *rdb_get_binlog_manager(void)
|
Rdb_binlog_manager *rdb_get_binlog_manager(void)
|
||||||
__attribute__((__warn_unused_result__));
|
MY_ATTRIBUTE((__warn_unused_result__));
|
||||||
|
|
||||||
} // namespace myrocks
|
} // namespace myrocks
|
||||||
|
@@ -21,13 +21,10 @@
|
|||||||
|
|
||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
class Rdb_logger : public rocksdb::Logger
|
class Rdb_logger : public rocksdb::Logger {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
void Logv(const rocksdb::InfoLogLevel log_level,
|
void Logv(const rocksdb::InfoLogLevel log_level, const char *format,
|
||||||
const char* format,
|
va_list ap) override {
|
||||||
va_list ap) override
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(format != nullptr);
|
DBUG_ASSERT(format != nullptr);
|
||||||
|
|
||||||
enum loglevel mysql_log_level;
|
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);
|
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);
|
DBUG_ASSERT(format != nullptr);
|
||||||
// If no level is specified, it is by default at information level
|
// If no level is specified, it is by default at information level
|
||||||
Logv(rocksdb::InfoLogLevel::INFO_LEVEL, format, ap);
|
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;
|
m_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,20 +4,20 @@ CREATE DATABASE mysqlslap;
|
|||||||
USE mysqlslap;
|
USE mysqlslap;
|
||||||
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
|
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
|
||||||
# 2PC enabled, MyRocks durability enabled
|
# 2PC enabled, MyRocks durability enabled
|
||||||
SET GLOBAL rocksdb_disable_2pc=0;
|
SET GLOBAL rocksdb_enable_2pc=0;
|
||||||
SET GLOBAL rocksdb_write_sync=1;
|
SET GLOBAL rocksdb_write_sync=1;
|
||||||
## 2PC + durability + single thread
|
## 2PC + durability + single thread
|
||||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
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';
|
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
|
case when variable_value-@c = 1000 then 'true' else 'false' end
|
||||||
true
|
false
|
||||||
## 2PC + durability + group commit
|
## 2PC + durability + group commit
|
||||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
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';
|
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
|
case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true' else 'false' end
|
||||||
true
|
false
|
||||||
# 2PC enabled, MyRocks durability disabled
|
# 2PC enabled, MyRocks durability disabled
|
||||||
SET GLOBAL rocksdb_disable_2pc=0;
|
SET GLOBAL rocksdb_enable_2pc=0;
|
||||||
SET GLOBAL rocksdb_write_sync=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 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';
|
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
|
case when variable_value-@c = 0 then 'true' else 'false' end
|
||||||
true
|
true
|
||||||
# 2PC disabled, MyRocks durability enabled
|
# 2PC disabled, MyRocks durability enabled
|
||||||
SET GLOBAL rocksdb_disable_2pc=1;
|
SET GLOBAL rocksdb_enable_2pc=1;
|
||||||
SET GLOBAL rocksdb_write_sync=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 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';
|
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
|
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 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';
|
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
|
case when variable_value-@c = 0 then 'true' else 'false' end
|
||||||
true
|
false
|
||||||
SET GLOBAL rocksdb_disable_2pc=1;
|
SET GLOBAL rocksdb_enable_2pc=1;
|
||||||
SET GLOBAL rocksdb_write_sync=0;
|
SET GLOBAL rocksdb_write_sync=0;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP DATABASE mysqlslap;
|
DROP DATABASE mysqlslap;
|
||||||
|
@@ -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
|
# crash_during_index_creation_partition
|
||||||
flush logs;
|
flush logs;
|
||||||
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
|
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;
|
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";
|
SET SESSION debug="-d,myrocks_simulate_index_create_rollback";
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
|
@@ -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;
|
@@ -10,19 +10,19 @@ SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
|||||||
WHERE INDEX_NUMBER =
|
WHERE INDEX_NUMBER =
|
||||||
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
||||||
WHERE TABLE_NAME = 't1' AND INDEX_NAME = "PRIMARY");
|
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
|
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
|
||||||
# # SSTNAME 5 # # # # #
|
# # SSTNAME 5 # # # # # 5
|
||||||
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
||||||
WHERE INDEX_NUMBER =
|
WHERE INDEX_NUMBER =
|
||||||
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
||||||
WHERE TABLE_NAME = 't1' AND INDEX_NAME = "j");
|
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
|
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
|
||||||
# # SSTNAME 5 # # # # #
|
# # SSTNAME 5 # # # # # 5,5
|
||||||
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
||||||
WHERE INDEX_NUMBER =
|
WHERE INDEX_NUMBER =
|
||||||
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
||||||
WHERE TABLE_NAME = 't2' AND INDEX_NAME = "PRIMARY");
|
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
|
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
|
||||||
# # SSTNAME 4 # # # # #
|
# # SSTNAME 4 # # # # # 4
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
|
@@ -9,6 +9,7 @@ CF_FLAGS 1 __system__ [0]
|
|||||||
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||||
count(*)
|
count(*)
|
||||||
3
|
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;
|
CREATE TABLE t1 (i1 INT, i2 INT, PRIMARY KEY (i1)) ENGINE = ROCKSDB;
|
||||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
||||||
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||||
@@ -22,6 +23,11 @@ CF_FLAGS 1 __system__ [0]
|
|||||||
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||||
count(*)
|
count(*)
|
||||||
6
|
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 tindex1 on t1 (i1);
|
||||||
CREATE INDEX tindex2 on t1 (i2);
|
CREATE INDEX tindex2 on t1 (i2);
|
||||||
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where TYPE = 'CF_FLAGS';
|
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where TYPE = 'CF_FLAGS';
|
||||||
|
@@ -121,7 +121,7 @@ a b
|
|||||||
5 loaded
|
5 loaded
|
||||||
7 test
|
7 test
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
set session rocksdb_skip_unique_check=1;
|
set session unique_checks=0;
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
CREATE TABLE t1 (a INT, b CHAR(8), pk INT AUTO_INCREMENT PRIMARY KEY) ENGINE=rocksdb;
|
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
|
LOAD DATA INFILE '<DATADIR>/se_loaddata.dat' INTO TABLE t1
|
||||||
|
11
storage/rocksdb/mysql-test/rocksdb/r/persistent_cache.result
Normal file
11
storage/rocksdb/mysql-test/rocksdb/r/persistent_cache.result
Normal 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;
|
@@ -890,8 +890,8 @@ rocksdb_deadlock_detect OFF
|
|||||||
rocksdb_debug_optimizer_no_zero_cardinality ON
|
rocksdb_debug_optimizer_no_zero_cardinality ON
|
||||||
rocksdb_default_cf_options
|
rocksdb_default_cf_options
|
||||||
rocksdb_delete_obsolete_files_period_micros 21600000000
|
rocksdb_delete_obsolete_files_period_micros 21600000000
|
||||||
rocksdb_disable_2pc ON
|
|
||||||
rocksdb_disabledatasync OFF
|
rocksdb_disabledatasync OFF
|
||||||
|
rocksdb_enable_2pc ON
|
||||||
rocksdb_enable_bulk_load_api ON
|
rocksdb_enable_bulk_load_api ON
|
||||||
rocksdb_enable_thread_tracking OFF
|
rocksdb_enable_thread_tracking OFF
|
||||||
rocksdb_enable_write_thread_adaptive_yield OFF
|
rocksdb_enable_write_thread_adaptive_yield OFF
|
||||||
@@ -924,17 +924,17 @@ rocksdb_override_cf_options
|
|||||||
rocksdb_paranoid_checks ON
|
rocksdb_paranoid_checks ON
|
||||||
rocksdb_pause_background_work ON
|
rocksdb_pause_background_work ON
|
||||||
rocksdb_perf_context_level 0
|
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_pin_l0_filter_and_index_blocks_in_cache ON
|
||||||
rocksdb_print_snapshot_conflict_queries OFF
|
rocksdb_print_snapshot_conflict_queries OFF
|
||||||
rocksdb_rate_limiter_bytes_per_sec 0
|
rocksdb_rate_limiter_bytes_per_sec 0
|
||||||
rocksdb_read_free_rpl_tables
|
rocksdb_read_free_rpl_tables
|
||||||
rocksdb_records_in_range 50
|
rocksdb_records_in_range 50
|
||||||
rocksdb_rpl_skip_tx_api OFF
|
|
||||||
rocksdb_seconds_between_stat_computes 3600
|
rocksdb_seconds_between_stat_computes 3600
|
||||||
rocksdb_signal_drop_index_thread OFF
|
rocksdb_signal_drop_index_thread OFF
|
||||||
rocksdb_skip_bloom_filter_on_read OFF
|
rocksdb_skip_bloom_filter_on_read OFF
|
||||||
rocksdb_skip_fill_cache OFF
|
rocksdb_skip_fill_cache OFF
|
||||||
rocksdb_skip_unique_check OFF
|
|
||||||
rocksdb_skip_unique_check_tables .*
|
rocksdb_skip_unique_check_tables .*
|
||||||
rocksdb_stats_dump_period_sec 600
|
rocksdb_stats_dump_period_sec 600
|
||||||
rocksdb_store_row_debug_checksums OFF
|
rocksdb_store_row_debug_checksums OFF
|
||||||
@@ -2231,7 +2231,7 @@ DROP DATABASE test_db;
|
|||||||
# Issue #143: Split rocksdb_bulk_load option into two
|
# Issue #143: Split rocksdb_bulk_load option into two
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (id int primary key, value int) engine=RocksDB;
|
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, 1);
|
||||||
INSERT INTO t1 VALUES(1, 2);
|
INSERT INTO t1 VALUES(1, 2);
|
||||||
INSERT INTO t1 VALUES(1, 3);
|
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
|
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;
|
TRUNCATE TABLE t1;
|
||||||
SET @save_rocksdb_bulk_load_size= @@rocksdb_bulk_load_size;
|
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_commit_in_the_middle=1;
|
||||||
SET rocksdb_bulk_load_size=10;
|
SET rocksdb_bulk_load_size=10;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@@ -6,9 +6,9 @@ Note #### Storing MySQL user name or password information in the master info rep
|
|||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
create table t1 (a int) engine=rocksdb;
|
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
|
Variable_name Value
|
||||||
rocksdb_rpl_skip_tx_api ON
|
rpl_skip_tx_api ON
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
found
|
found
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@@ -183,3 +183,24 @@ ERROR 23000: Duplicate entry '1-1' for key 'PRIMARY'
|
|||||||
INSERT INTO t2 VALUES (2,1);
|
INSERT INTO t2 VALUES (2,1);
|
||||||
ERROR 23000: Duplicate entry '1' for key 'a'
|
ERROR 23000: Duplicate entry '1' for key 'a'
|
||||||
DROP TABLE t2;
|
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;
|
||||||
|
@@ -13,7 +13,7 @@ USE mysqlslap;
|
|||||||
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
|
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
|
||||||
|
|
||||||
--echo # 2PC enabled, MyRocks durability enabled
|
--echo # 2PC enabled, MyRocks durability enabled
|
||||||
SET GLOBAL rocksdb_disable_2pc=0;
|
SET GLOBAL rocksdb_enable_2pc=0;
|
||||||
SET GLOBAL rocksdb_write_sync=1;
|
SET GLOBAL rocksdb_write_sync=1;
|
||||||
|
|
||||||
--echo ## 2PC + durability + single thread
|
--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
|
--echo # 2PC enabled, MyRocks durability disabled
|
||||||
SET GLOBAL rocksdb_disable_2pc=0;
|
SET GLOBAL rocksdb_enable_2pc=0;
|
||||||
SET GLOBAL rocksdb_write_sync=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 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
|
--echo # 2PC disabled, MyRocks durability enabled
|
||||||
SET GLOBAL rocksdb_disable_2pc=1;
|
SET GLOBAL rocksdb_enable_2pc=1;
|
||||||
SET GLOBAL rocksdb_write_sync=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 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;
|
SET GLOBAL rocksdb_write_sync=0;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP DATABASE mysqlslap;
|
DROP DATABASE mysqlslap;
|
||||||
|
@@ -89,22 +89,11 @@ while ($i <= $max) {
|
|||||||
--echo # crash_during_index_creation_partition
|
--echo # crash_during_index_creation_partition
|
||||||
flush logs;
|
flush logs;
|
||||||
|
|
||||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
|
||||||
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
|
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
|
||||||
|
|
||||||
--echo # expected assertion failure from sql layer here for alter rollback
|
--error 1105
|
||||||
call mtr.add_suppression("Assertion `0' failed.");
|
|
||||||
call mtr.add_suppression("Attempting backtrace. You can use the following information to find out");
|
|
||||||
|
|
||||||
--error 2013
|
|
||||||
|
|
||||||
ALTER TABLE t1 ADD INDEX kij(i,j), ALGORITHM=INPLACE;
|
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";
|
SET SESSION debug="-d,myrocks_simulate_index_create_rollback";
|
||||||
|
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
|
|
||||||
# here, the index numbers should be higher because previously 4 index numbers
|
# here, the index numbers should be higher because previously 4 index numbers
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
|
@@ -12,6 +12,8 @@ DROP TABLE IF EXISTS t3;
|
|||||||
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||||
select count(*) 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;
|
CREATE TABLE t1 (i1 INT, i2 INT, PRIMARY KEY (i1)) ENGINE = ROCKSDB;
|
||||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
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 * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||||
select count(*) 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);
|
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)
|
--let $start_max_index_id = query_get_value(SELECT * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where type = 'MAX_INDEX_ID', VALUE, 1)
|
||||||
|
|
||||||
|
@@ -3,6 +3,5 @@
|
|||||||
let $skip_unique_check = 0;
|
let $skip_unique_check = 0;
|
||||||
--source loaddata.inc
|
--source loaddata.inc
|
||||||
let $skip_unique_check = 1;
|
let $skip_unique_check = 1;
|
||||||
set session rocksdb_skip_unique_check=1;
|
set session unique_checks=0;
|
||||||
--source loaddata.inc
|
--source loaddata.inc
|
||||||
|
|
||||||
|
41
storage/rocksdb/mysql-test/rocksdb/t/persistent_cache.test
Normal file
41
storage/rocksdb/mysql-test/rocksdb/t/persistent_cache.test
Normal 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;
|
@@ -1768,7 +1768,7 @@ DROP DATABASE test_db;
|
|||||||
--echo # Issue #143: Split rocksdb_bulk_load option into two
|
--echo # Issue #143: Split rocksdb_bulk_load option into two
|
||||||
--echo #
|
--echo #
|
||||||
CREATE TABLE t1 (id int primary key, value int) engine=RocksDB;
|
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, 1);
|
||||||
INSERT INTO t1 VALUES(1, 2);
|
INSERT INTO t1 VALUES(1, 2);
|
||||||
INSERT INTO t1 VALUES(1, 3);
|
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;
|
INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1;
|
||||||
TRUNCATE TABLE t1;
|
TRUNCATE TABLE t1;
|
||||||
SET @save_rocksdb_bulk_load_size= @@rocksdb_bulk_load_size;
|
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_commit_in_the_middle=1;
|
||||||
SET rocksdb_bulk_load_size=10;
|
SET rocksdb_bulk_load_size=10;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@@ -5,4 +5,4 @@ binlog_format=row
|
|||||||
[mysqld.2]
|
[mysqld.2]
|
||||||
binlog_format=row
|
binlog_format=row
|
||||||
slave_parallel_workers=1
|
slave_parallel_workers=1
|
||||||
rocksdb_rpl_skip_tx_api=ON
|
rpl_skip_tx_api=ON
|
||||||
|
@@ -17,7 +17,7 @@ while ($aa < 1000) {
|
|||||||
--enable_query_log
|
--enable_query_log
|
||||||
|
|
||||||
connection slave;
|
connection slave;
|
||||||
show variables like 'rocksdb_rpl_skip_tx_api';
|
show variables like 'rpl_skip_tx_api';
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
|
|
||||||
--let $it=0
|
--let $it=0
|
||||||
|
@@ -31,3 +31,21 @@ INSERT INTO t2 VALUES (1,1);
|
|||||||
--error ER_DUP_ENTRY
|
--error ER_DUP_ENTRY
|
||||||
INSERT INTO t2 VALUES (2,1);
|
INSERT INTO t2 VALUES (2,1);
|
||||||
DROP TABLE t2;
|
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;
|
||||||
|
@@ -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')"
|
43
storage/rocksdb/mysql-test/rocksdb_hotbackup/include/load_data_slocket.sh
Executable file
43
storage/rocksdb/mysql-test/rocksdb_hotbackup/include/load_data_slocket.sh
Executable 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
|
@@ -0,0 +1,2 @@
|
|||||||
|
src_data_dir="${MYSQLTEST_VARDIR}/mysqld.1/data/"
|
||||||
|
rm "${src_data_dir}/slocket"
|
@@ -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;
|
@@ -39,6 +39,11 @@ elif [ "$STREAM_TYPE" == 'xbstream' ]; then
|
|||||||
--stream=xbstream --checkpoint_dir=$checkpoint_dir 2> \
|
--stream=xbstream --checkpoint_dir=$checkpoint_dir 2> \
|
||||||
$COPY_LOG | xbstream -x \
|
$COPY_LOG | xbstream -x \
|
||||||
--directory=$backup_dir"
|
--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
|
else
|
||||||
BACKUP_CMD="$MYSQL_MYROCKS_HOTBACKUP --user='root' --stream=wdt \
|
BACKUP_CMD="$MYSQL_MYROCKS_HOTBACKUP --user='root' --stream=wdt \
|
||||||
--port=${MASTER_MYPORT} --destination=localhost --backup_dir=$backup_dir \
|
--port=${MASTER_MYPORT} --destination=localhost --backup_dir=$backup_dir \
|
||||||
|
@@ -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
|
@@ -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
|
46
storage/rocksdb/mysql-test/rocksdb_hotbackup/t/slocket.test
Normal file
46
storage/rocksdb/mysql-test/rocksdb_hotbackup/t/slocket.test
Normal 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;
|
@@ -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;
|
||||||
|
|
@@ -1,5 +1,5 @@
|
|||||||
DROP TABLE IF EXISTS t1;
|
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;
|
create table t1 (a int primary key, b int, c varchar(255)) engine=rocksdb;
|
||||||
'con1'
|
'con1'
|
||||||
SET SESSION debug="d,crash_commit_after_log";
|
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");;
|
insert into t1 values (1, 1, "iamtheogthealphaandomega");;
|
||||||
'con2'
|
'con2'
|
||||||
insert into t1 values (2, 1, "i_am_just_here_to_trigger_a_flush");
|
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 ROCKSDB_WRITE_SYNC = OFF;
|
||||||
SET GLOBAL SYNC_BINLOG = 0;
|
SET GLOBAL SYNC_BINLOG = 0;
|
||||||
SET DEBUG_SYNC='now WAIT_FOR parked';
|
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 ROCKSDB_WRITE_SYNC = ON;
|
||||||
SET GLOBAL SYNC_BINLOG = 1;
|
SET GLOBAL SYNC_BINLOG = 1;
|
||||||
insert into t1 values (1000000, 1, "i_am_just_here_to_trigger_a_flush");
|
insert into t1 values (1000000, 1, "i_am_just_here_to_trigger_a_flush");
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
create table t1 (a int primary key, msg varchar(255)) engine=rocksdb;
|
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";
|
SET SESSION debug="d,crash_commit_after_prepare";
|
||||||
insert into t1 values (1, 'dogz');
|
insert into t1 values (1, 'dogz');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a msg
|
a msg
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||||
SET SESSION debug="d,crash_commit_after_log";
|
SET SESSION debug="d,crash_commit_after_log";
|
||||||
insert into t1 values (2, 'catz'), (3, 'men');
|
insert into t1 values (2, 'catz'), (3, 'men');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a msg
|
a msg
|
||||||
2 catz
|
2 catz
|
||||||
3 men
|
3 men
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||||
SET SESSION debug="d,crash_commit_after";
|
SET SESSION debug="d,crash_commit_after";
|
||||||
insert into t1 values (4, 'cars'), (5, 'foo');
|
insert into t1 values (4, 'cars'), (5, 'foo');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
@@ -21,7 +21,7 @@ a msg
|
|||||||
3 men
|
3 men
|
||||||
4 cars
|
4 cars
|
||||||
5 foo
|
5 foo
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||||
SET SESSION debug="d,crash_commit_after_log";
|
SET SESSION debug="d,crash_commit_after_log";
|
||||||
insert into t1 values (6, 'shipz'), (7, 'tankz');
|
insert into t1 values (6, 'shipz'), (7, 'tankz');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
@@ -30,7 +30,7 @@ a msg
|
|||||||
3 men
|
3 men
|
||||||
4 cars
|
4 cars
|
||||||
5 foo
|
5 foo
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||||
SET SESSION debug="d,crash_commit_after";
|
SET SESSION debug="d,crash_commit_after";
|
||||||
insert into t1 values (8, 'space'), (9, 'time');
|
insert into t1 values (8, 'space'), (9, 'time');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
@@ -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
|
@@ -10,7 +10,7 @@
|
|||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
--enable_warnings
|
--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;
|
create table t1 (a int primary key, b int, c varchar(255)) engine=rocksdb;
|
||||||
|
|
||||||
connect (con1, localhost, root,,);
|
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
|
# Disable 2PC and syncing for faster inserting of dummy rows
|
||||||
# These rows only purpose is to rotate the binlog
|
# 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 ROCKSDB_WRITE_SYNC = OFF;
|
||||||
SET GLOBAL SYNC_BINLOG = 0;
|
SET GLOBAL SYNC_BINLOG = 0;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ while ($pk < 1000000) {
|
|||||||
|
|
||||||
# re-enable 2PC an syncing then write to trigger a flush
|
# re-enable 2PC an syncing then write to trigger a flush
|
||||||
# before we trigger the crash to simulate full-durability
|
# 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 ROCKSDB_WRITE_SYNC = ON;
|
||||||
SET GLOBAL SYNC_BINLOG = 1;
|
SET GLOBAL SYNC_BINLOG = 1;
|
||||||
|
|
||||||
|
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
[mysqld.1]
|
[mysqld.1]
|
||||||
log_slave_updates
|
log_slave_updates
|
||||||
|
rocksdb_enable_2pc=OFF
|
||||||
|
|
||||||
[mysqld.2]
|
[mysqld.2]
|
||||||
relay_log_recovery=1
|
relay_log_recovery=1
|
||||||
relay_log_info_repository=TABLE
|
relay_log_info_repository=TABLE
|
||||||
log_slave_updates
|
log_slave_updates
|
||||||
|
rocksdb_enable_2pc=OFF
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
log_slave_updates
|
log_slave_updates
|
||||||
gtid_mode=ON
|
gtid_mode=ON
|
||||||
enforce_gtid_consistency=ON
|
enforce_gtid_consistency=ON
|
||||||
|
rocksdb_enable_2pc=OFF
|
||||||
|
|
||||||
[mysqld.2]
|
[mysqld.2]
|
||||||
sync_relay_log_info=100
|
sync_relay_log_info=100
|
||||||
@@ -12,3 +13,4 @@ relay_log_info_repository=FILE
|
|||||||
log_slave_updates
|
log_slave_updates
|
||||||
gtid_mode=ON
|
gtid_mode=ON
|
||||||
enforce_gtid_consistency=ON
|
enforce_gtid_consistency=ON
|
||||||
|
rocksdb_enable_2pc=OFF
|
||||||
|
@@ -8,7 +8,7 @@ DROP TABLE IF EXISTS t1;
|
|||||||
|
|
||||||
create table t1 (a int primary key, msg varchar(255)) engine=rocksdb;
|
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
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
SET SESSION debug="d,crash_commit_after_prepare";
|
SET SESSION debug="d,crash_commit_after_prepare";
|
||||||
--error 0,2013
|
--error 0,2013
|
||||||
@@ -17,7 +17,7 @@ insert into t1 values (1, 'dogz');
|
|||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
SET SESSION debug="d,crash_commit_after_log";
|
SET SESSION debug="d,crash_commit_after_log";
|
||||||
--error 0,2013
|
--error 0,2013
|
||||||
@@ -26,7 +26,7 @@ insert into t1 values (2, 'catz'), (3, 'men');
|
|||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
SET SESSION debug="d,crash_commit_after";
|
SET SESSION debug="d,crash_commit_after";
|
||||||
--error 0,2013
|
--error 0,2013
|
||||||
@@ -35,7 +35,7 @@ insert into t1 values (4, 'cars'), (5, 'foo');
|
|||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
SET SESSION debug="d,crash_commit_after_log";
|
SET SESSION debug="d,crash_commit_after_log";
|
||||||
--error 0,2013
|
--error 0,2013
|
||||||
@@ -44,7 +44,7 @@ insert into t1 values (6, 'shipz'), (7, 'tankz');
|
|||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
|
||||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
SET SESSION debug="d,crash_commit_after";
|
SET SESSION debug="d,crash_commit_after";
|
||||||
--error 0,2013
|
--error 0,2013
|
||||||
|
@@ -0,0 +1,2 @@
|
|||||||
|
--gtid_mode=ON --enforce_gtid_consistency --log_slave_updates
|
||||||
|
--binlog_format=STATEMENT --default-storage-engine=rocksdb
|
@@ -0,0 +1,2 @@
|
|||||||
|
--gtid_mode=ON --enforce_gtid_consistency --log_slave_updates
|
||||||
|
--sync_binlog=1000 --relay_log_recovery=1 --default-storage-engine=rocksdb
|
@@ -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
|
@@ -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
|
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;
|
left join t1 on variable_name=test_name where test_name is null ORDER BY variable_name;
|
||||||
There should be *no* variables listed below:
|
There should be *no* variables listed below:
|
||||||
|
ROCKSDB_ENABLE_2PC
|
||||||
|
ROCKSDB_ENABLE_2PC
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
@@ -6,70 +6,70 @@ INSERT INTO valid_values VALUES('off');
|
|||||||
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
||||||
INSERT INTO invalid_values VALUES('\'aaa\'');
|
INSERT INTO invalid_values VALUES('\'aaa\'');
|
||||||
INSERT INTO invalid_values VALUES('\'bbb\'');
|
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;
|
SELECT @start_global_value;
|
||||||
@start_global_value
|
@start_global_value
|
||||||
1
|
1
|
||||||
'# Setting to valid values in global scope#'
|
'# Setting to valid values in global scope#'
|
||||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 1"
|
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 1"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = 1;
|
SET @@global.ROCKSDB_ENABLE_2PC = 1;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Setting the global scope variable back to default"
|
"Setting the global scope variable back to default"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 0"
|
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 0"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = 0;
|
SET @@global.ROCKSDB_ENABLE_2PC = 0;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
0
|
0
|
||||||
"Setting the global scope variable back to default"
|
"Setting the global scope variable back to default"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to on"
|
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to on"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = on;
|
SET @@global.ROCKSDB_ENABLE_2PC = on;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Setting the global scope variable back to default"
|
"Setting the global scope variable back to default"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to off"
|
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to off"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = off;
|
SET @@global.ROCKSDB_ENABLE_2PC = off;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
0
|
0
|
||||||
"Setting the global scope variable back to default"
|
"Setting the global scope variable back to default"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Trying to set variable @@session.ROCKSDB_DISABLE_2PC to 444. It should fail because it is not session."
|
"Trying to set variable @@session.ROCKSDB_ENABLE_2PC to 444. It should fail because it is not session."
|
||||||
SET @@session.ROCKSDB_DISABLE_2PC = 444;
|
SET @@session.ROCKSDB_ENABLE_2PC = 444;
|
||||||
ERROR HY000: Variable 'rocksdb_disable_2pc' is a GLOBAL variable and should be set with SET GLOBAL
|
ERROR HY000: Variable 'rocksdb_enable_2pc' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
'# Testing with invalid values in global scope #'
|
'# Testing with invalid values in global scope #'
|
||||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 'aaa'"
|
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 'aaa'"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = 'aaa';
|
SET @@global.ROCKSDB_ENABLE_2PC = 'aaa';
|
||||||
Got one of the listed errors
|
Got one of the listed errors
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 'bbb'"
|
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 'bbb'"
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = 'bbb';
|
SET @@global.ROCKSDB_ENABLE_2PC = 'bbb';
|
||||||
Got one of the listed errors
|
Got one of the listed errors
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
SET @@global.ROCKSDB_DISABLE_2PC = @start_global_value;
|
SET @@global.ROCKSDB_ENABLE_2PC = @start_global_value;
|
||||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||||
@@global.ROCKSDB_DISABLE_2PC
|
@@global.ROCKSDB_ENABLE_2PC
|
||||||
1
|
1
|
||||||
DROP TABLE valid_values;
|
DROP TABLE valid_values;
|
||||||
DROP TABLE invalid_values;
|
DROP TABLE invalid_values;
|
||||||
|
@@ -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;
|
SET @start_global_value = @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||||
SELECT @start_global_value;
|
SELECT @start_global_value;
|
||||||
@start_global_value
|
@start_global_value
|
||||||
1
|
1
|
||||||
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 444. It should fail because it is readonly."
|
'# Setting to valid values in global scope#'
|
||||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 444;
|
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 1"
|
||||||
ERROR HY000: Variable 'rocksdb_max_background_compactions' is a read only variable
|
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;
|
||||||
|
@@ -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;
|
@@ -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;
|
@@ -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;
|
|
@@ -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;
|
|
@@ -10,7 +10,7 @@ CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
|||||||
INSERT INTO invalid_values VALUES('\'aaa\'');
|
INSERT INTO invalid_values VALUES('\'aaa\'');
|
||||||
INSERT INTO invalid_values VALUES('\'bbb\'');
|
INSERT INTO invalid_values VALUES('\'bbb\'');
|
||||||
|
|
||||||
--let $sys_var=ROCKSDB_DISABLE_2PC
|
--let $sys_var=ROCKSDB_ENABLE_2PC
|
||||||
--let $read_only=0
|
--let $read_only=0
|
||||||
--let $session=0
|
--let $session=0
|
||||||
--let $sticky=1
|
--let $sticky=1
|
||||||
|
@@ -1,7 +1,16 @@
|
|||||||
--source include/have_rocksdb.inc
|
--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 $sys_var=ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||||
--let $read_only=1
|
--let $read_only=0
|
||||||
--let $session=0
|
--let $session=0
|
||||||
--source suite/sys_vars/inc/rocksdb_sys_var.inc
|
--source suite/sys_vars/inc/rocksdb_sys_var.inc
|
||||||
|
|
||||||
|
DROP TABLE valid_values;
|
||||||
|
DROP TABLE invalid_values;
|
||||||
|
@@ -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;
|
@@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
|
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
|
||||||
INSERT INTO valid_values VALUES(1);
|
INSERT INTO valid_values VALUES(1);
|
||||||
INSERT INTO valid_values VALUES(0);
|
INSERT INTO valid_values VALUES(1024);
|
||||||
INSERT INTO valid_values VALUES('on');
|
|
||||||
INSERT INTO valid_values VALUES('off');
|
|
||||||
|
|
||||||
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
||||||
INSERT INTO invalid_values VALUES('\'aaa\'');
|
INSERT INTO invalid_values VALUES('\'aaa\'');
|
||||||
|
|
||||||
--let $sys_var=ROCKSDB_RPL_SKIP_TX_API
|
--let $sys_var=ROCKSDB_PERSISTENT_CACHE_SIZE
|
||||||
--let $read_only=0
|
--let $read_only=1
|
||||||
--let $session=0
|
--let $session=0
|
||||||
--source suite/sys_vars/inc/rocksdb_sys_var.inc
|
--source suite/sys_vars/inc/rocksdb_sys_var.inc
|
||||||
|
|
@@ -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;
|
|
@@ -41,21 +41,15 @@ std::atomic<uint64_t> rocksdb_num_sst_entry_merge(0);
|
|||||||
std::atomic<uint64_t> rocksdb_num_sst_entry_other(0);
|
std::atomic<uint64_t> rocksdb_num_sst_entry_other(0);
|
||||||
my_bool rocksdb_compaction_sequential_deletes_count_sd = false;
|
my_bool rocksdb_compaction_sequential_deletes_count_sd = false;
|
||||||
|
|
||||||
Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(
|
Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
|
||||||
Rdb_ddl_manager* const ddl_manager,
|
|
||||||
const Rdb_compact_params ¶ms,
|
const Rdb_compact_params ¶ms,
|
||||||
const uint32_t &cf_id,
|
const uint32_t &cf_id,
|
||||||
const uint8_t &table_stats_sampling_pct
|
const uint8_t &table_stats_sampling_pct)
|
||||||
) :
|
: m_cf_id(cf_id), m_ddl_manager(ddl_manager), m_last_stats(nullptr),
|
||||||
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_rows(0l), m_window_pos(0l), m_deleted_rows(0l), m_max_deleted_rows(0l),
|
||||||
m_file_size(0), m_params(params),
|
m_file_size(0), m_params(params),
|
||||||
m_table_stats_sampling_pct(table_stats_sampling_pct),
|
m_table_stats_sampling_pct(table_stats_sampling_pct),
|
||||||
m_seed(time(nullptr)),
|
m_seed(time(nullptr)), m_card_adj_extra(1.) {
|
||||||
m_card_adj_extra(1.)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(ddl_manager != nullptr);
|
DBUG_ASSERT(ddl_manager != nullptr);
|
||||||
|
|
||||||
// We need to adjust the index cardinality numbers based on the sampling
|
// 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
|
This function is called by RocksDB for every key in the SST file
|
||||||
*/
|
*/
|
||||||
rocksdb::Status
|
rocksdb::Status Rdb_tbl_prop_coll::AddUserKey(const rocksdb::Slice &key,
|
||||||
Rdb_tbl_prop_coll::AddUserKey(
|
const rocksdb::Slice &value,
|
||||||
const rocksdb::Slice& key, const rocksdb::Slice& value,
|
rocksdb::EntryType type,
|
||||||
rocksdb::EntryType type, rocksdb::SequenceNumber seq,
|
rocksdb::SequenceNumber seq,
|
||||||
uint64_t file_size
|
uint64_t file_size) {
|
||||||
) {
|
|
||||||
if (key.size() >= 4) {
|
if (key.size() >= 4) {
|
||||||
AdjustDeletedRows(type);
|
AdjustDeletedRows(type);
|
||||||
|
|
||||||
@@ -88,10 +81,8 @@ Rdb_tbl_prop_coll::AddUserKey(
|
|||||||
return rocksdb::Status::OK();
|
return rocksdb::Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type)
|
void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type) {
|
||||||
{
|
if (m_params.m_window > 0) {
|
||||||
if (m_params.m_window > 0)
|
|
||||||
{
|
|
||||||
// record the "is deleted" flag into the sliding window
|
// record the "is deleted" flag into the sliding window
|
||||||
// the sliding window is implemented as a circular buffer
|
// the sliding window is implemented as a circular buffer
|
||||||
// in m_deleted_rows_window vector
|
// 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));
|
rocksdb_compaction_sequential_deletes_count_sd));
|
||||||
|
|
||||||
// Only make changes if the value at the current position needs to change
|
// 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
|
// Set or clear the flag at the current position as appropriate
|
||||||
m_deleted_rows_window[m_window_pos] = is_delete;
|
m_deleted_rows_window[m_window_pos] = is_delete;
|
||||||
if (!is_delete)
|
if (!is_delete) {
|
||||||
{
|
|
||||||
m_deleted_rows--;
|
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;
|
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;
|
m_window_pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
|
Rdb_index_stats *Rdb_tbl_prop_coll::AccessStats(const rocksdb::Slice &key) {
|
||||||
const rocksdb::Slice& key)
|
GL_INDEX_ID gl_index_id = {.cf_id = m_cf_id,
|
||||||
{
|
.index_id = rdb_netbuf_to_uint32(
|
||||||
GL_INDEX_ID gl_index_id = {
|
reinterpret_cast<const uchar *>(key.data()))};
|
||||||
.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;
|
m_keydef = nullptr;
|
||||||
|
|
||||||
// starting a new table
|
// starting a new table
|
||||||
@@ -142,8 +124,7 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
|
|||||||
m_stats.emplace_back(gl_index_id);
|
m_stats.emplace_back(gl_index_id);
|
||||||
m_last_stats = &m_stats.back();
|
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
|
// 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
|
// 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
|
// 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
|
// when we are switching to a new Rdb_key_def and when this object
|
||||||
// is destructed.
|
// is destructed.
|
||||||
m_keydef = m_ddl_manager->safe_find(gl_index_id);
|
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.
|
// resize the array to the number of columns.
|
||||||
// It will be initialized with zeroes
|
// It will be initialized with zeroes
|
||||||
m_last_stats->m_distinct_keys_per_prefix.resize(
|
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;
|
return m_last_stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_tbl_prop_coll::CollectStatsForRow(
|
void Rdb_tbl_prop_coll::CollectStatsForRow(const rocksdb::Slice &key,
|
||||||
const rocksdb::Slice& key, const rocksdb::Slice& value,
|
const rocksdb::Slice &value,
|
||||||
const rocksdb::EntryType &type, const uint64_t &file_size)
|
const rocksdb::EntryType &type,
|
||||||
{
|
const uint64_t &file_size) {
|
||||||
const auto stats = AccessStats(key);
|
const auto stats = AccessStats(key);
|
||||||
|
|
||||||
stats->m_data_size += key.size() + value.size();
|
stats->m_data_size += key.size() + value.size();
|
||||||
@@ -195,7 +175,8 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
|
|||||||
default:
|
default:
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("RocksDB: Unexpected entry type found: %u. "
|
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();
|
abort_with_stack_traces();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -203,23 +184,19 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
|
|||||||
stats->m_actual_disk_size += file_size - m_file_size;
|
stats->m_actual_disk_size += file_size - m_file_size;
|
||||||
m_file_size = file_size;
|
m_file_size = file_size;
|
||||||
|
|
||||||
if (m_keydef != nullptr && ShouldCollectStats())
|
if (m_keydef != nullptr && ShouldCollectStats()) {
|
||||||
{
|
|
||||||
std::size_t column = 0;
|
std::size_t column = 0;
|
||||||
bool new_key = true;
|
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());
|
rocksdb::Slice last(m_last_key.data(), m_last_key.size());
|
||||||
new_key = (m_keydef->compare_keys(&last, &key, &column) == 0);
|
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());
|
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]++;
|
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 one of the first n-1 columns is different
|
||||||
// If the n-1 prefix is the same, no sense in storing
|
// If the n-1 prefix is the same, no sense in storing
|
||||||
// the new key
|
// 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());
|
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
|
This function is called by RocksDB to compute properties to store in sst file
|
||||||
*/
|
*/
|
||||||
rocksdb::Status
|
rocksdb::Status
|
||||||
Rdb_tbl_prop_coll::Finish(
|
Rdb_tbl_prop_coll::Finish(rocksdb::UserCollectedProperties *const properties) {
|
||||||
rocksdb::UserCollectedProperties* const properties
|
|
||||||
) {
|
|
||||||
uint64_t num_sst_entry_put = 0;
|
uint64_t num_sst_entry_put = 0;
|
||||||
uint64_t num_sst_entry_delete = 0;
|
uint64_t num_sst_entry_delete = 0;
|
||||||
uint64_t num_sst_entry_singledelete = 0;
|
uint64_t num_sst_entry_singledelete = 0;
|
||||||
@@ -253,8 +227,7 @@ Rdb_tbl_prop_coll::Finish(
|
|||||||
|
|
||||||
DBUG_ASSERT(properties != nullptr);
|
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_put += it->m_rows;
|
||||||
num_sst_entry_delete += it->m_entry_deletes;
|
num_sst_entry_delete += it->m_entry_deletes;
|
||||||
num_sst_entry_singledelete += it->m_entry_single_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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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 {
|
bool Rdb_tbl_prop_coll::NeedCompact() const {
|
||||||
return
|
return m_params.m_deletes && (m_params.m_window > 0) &&
|
||||||
m_params.m_deletes &&
|
|
||||||
(m_params.m_window > 0) &&
|
|
||||||
(m_file_size > m_params.m_file_size) &&
|
(m_file_size > m_params.m_file_size) &&
|
||||||
(m_max_deleted_rows > m_params.m_deletes);
|
(m_max_deleted_rows > m_params.m_deletes);
|
||||||
}
|
}
|
||||||
@@ -307,8 +273,8 @@ bool Rdb_tbl_prop_coll::ShouldCollectStats() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int val = rand_r(&m_seed) %
|
const int val = rand_r(&m_seed) % (RDB_TBL_STATS_SAMPLE_PCT_MAX -
|
||||||
(RDB_TBL_STATS_SAMPLE_PCT_MAX - RDB_TBL_STATS_SAMPLE_PCT_MIN + 1) +
|
RDB_TBL_STATS_SAMPLE_PCT_MIN + 1) +
|
||||||
RDB_TBL_STATS_SAMPLE_PCT_MIN;
|
RDB_TBL_STATS_SAMPLE_PCT_MIN;
|
||||||
|
|
||||||
DBUG_ASSERT(val >= 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}};
|
return rocksdb::UserCollectedProperties{{INDEXSTATS_KEY, s}};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string Rdb_tbl_prop_coll::GetReadableStats(const Rdb_index_stats &it) {
|
||||||
Rdb_tbl_prop_coll::GetReadableStats(
|
|
||||||
const Rdb_index_stats& it
|
|
||||||
) {
|
|
||||||
std::string s;
|
std::string s;
|
||||||
s.append("(");
|
s.append("(");
|
||||||
s.append(std::to_string(it.m_gl_index_id.cf_id));
|
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(
|
void Rdb_tbl_prop_coll::read_stats_from_tbl_props(
|
||||||
const std::shared_ptr<const rocksdb::TableProperties> &table_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);
|
DBUG_ASSERT(out_stats_vector != nullptr);
|
||||||
const auto &user_properties = table_props->user_collected_properties;
|
const auto &user_properties = table_props->user_collected_properties;
|
||||||
const auto it2 = user_properties.find(std::string(INDEXSTATS_KEY));
|
const auto it2 = user_properties.find(std::string(INDEXSTATS_KEY));
|
||||||
if (it2 != user_properties.end())
|
if (it2 != user_properties.end()) {
|
||||||
{
|
auto result MY_ATTRIBUTE((__unused__)) =
|
||||||
auto result __attribute__((__unused__)) =
|
|
||||||
Rdb_index_stats::unmaterialize(it2->second, out_stats_vector);
|
Rdb_index_stats::unmaterialize(it2->second, out_stats_vector);
|
||||||
DBUG_ASSERT(result == 0);
|
DBUG_ASSERT(result == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Serializes an array of Rdb_index_stats into a network string.
|
Serializes an array of Rdb_index_stats into a network string.
|
||||||
*/
|
*/
|
||||||
std::string Rdb_index_stats::materialize(
|
std::string
|
||||||
const std::vector<Rdb_index_stats>& stats,
|
Rdb_index_stats::materialize(const std::vector<Rdb_index_stats> &stats,
|
||||||
const float card_adj_extra)
|
const float card_adj_extra) {
|
||||||
{
|
|
||||||
String ret;
|
String ret;
|
||||||
rdb_netstr_append_uint16(&ret, INDEX_STATS_VERSION_ENTRY_TYPES);
|
rdb_netstr_append_uint16(&ret, INDEX_STATS_VERSION_ENTRY_TYPES);
|
||||||
for (const auto &i : stats) {
|
for (const auto &i : stats) {
|
||||||
@@ -428,99 +387,86 @@ std::string Rdb_index_stats::materialize(
|
|||||||
/**
|
/**
|
||||||
@brief
|
@brief
|
||||||
Reads an array of Rdb_index_stats from a string.
|
Reads an array of Rdb_index_stats from a string.
|
||||||
@return 1 if it detects any inconsistency in the input
|
@return HA_EXIT_FAILURE if it detects any inconsistency in the input
|
||||||
@return 0 if completes successfully
|
@return HA_EXIT_SUCCESS if completes successfully
|
||||||
*/
|
*/
|
||||||
int Rdb_index_stats::unmaterialize(
|
int Rdb_index_stats::unmaterialize(const std::string &s,
|
||||||
const std::string& s, std::vector<Rdb_index_stats>* const ret)
|
std::vector<Rdb_index_stats> *const ret) {
|
||||||
{
|
|
||||||
const uchar *p = rdb_std_str_to_uchar_ptr(s);
|
const uchar *p = rdb_std_str_to_uchar_ptr(s);
|
||||||
const uchar *const p2 = p + s.size();
|
const uchar *const p2 = p + s.size();
|
||||||
|
|
||||||
DBUG_ASSERT(ret != nullptr);
|
DBUG_ASSERT(ret != nullptr);
|
||||||
|
|
||||||
if (p+2 > p2)
|
if (p + 2 > p2) {
|
||||||
{
|
return HA_EXIT_FAILURE;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int version = rdb_netbuf_read_uint16(&p);
|
const int version = rdb_netbuf_read_uint16(&p);
|
||||||
Rdb_index_stats stats;
|
Rdb_index_stats stats;
|
||||||
// Make sure version is within supported range.
|
// Make sure version is within supported range.
|
||||||
if (version < INDEX_STATS_VERSION_INITIAL ||
|
if (version < INDEX_STATS_VERSION_INITIAL ||
|
||||||
version > INDEX_STATS_VERSION_ENTRY_TYPES)
|
version > INDEX_STATS_VERSION_ENTRY_TYPES) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Index stats version %d was outside of supported range. "
|
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();
|
abort_with_stack_traces();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t needed = sizeof(stats.m_gl_index_id.cf_id) +
|
size_t needed = sizeof(stats.m_gl_index_id.cf_id) +
|
||||||
sizeof(stats.m_gl_index_id.index_id) +
|
sizeof(stats.m_gl_index_id.index_id) +
|
||||||
sizeof(stats.m_data_size)+
|
sizeof(stats.m_data_size) + sizeof(stats.m_rows) +
|
||||||
sizeof(stats.m_rows)+
|
sizeof(stats.m_actual_disk_size) + sizeof(uint64);
|
||||||
sizeof(stats.m_actual_disk_size)+
|
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES) {
|
||||||
sizeof(uint64);
|
|
||||||
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES)
|
|
||||||
{
|
|
||||||
needed += sizeof(stats.m_entry_deletes) +
|
needed += sizeof(stats.m_entry_deletes) +
|
||||||
sizeof(stats.m_entry_single_deletes) +
|
sizeof(stats.m_entry_single_deletes) +
|
||||||
sizeof(stats.m_entry_merges)+
|
sizeof(stats.m_entry_merges) + sizeof(stats.m_entry_others);
|
||||||
sizeof(stats.m_entry_others);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p < p2)
|
while (p < p2) {
|
||||||
{
|
if (p + needed > p2) {
|
||||||
if (p+needed > p2)
|
return HA_EXIT_FAILURE;
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
rdb_netbuf_read_gl_index(&p, &stats.m_gl_index_id);
|
rdb_netbuf_read_gl_index(&p, &stats.m_gl_index_id);
|
||||||
stats.m_data_size = rdb_netbuf_read_uint64(&p);
|
stats.m_data_size = rdb_netbuf_read_uint64(&p);
|
||||||
stats.m_rows = 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_actual_disk_size = rdb_netbuf_read_uint64(&p);
|
||||||
stats.m_distinct_keys_per_prefix.resize(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_deletes = rdb_netbuf_read_uint64(&p);
|
||||||
stats.m_entry_single_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_merges = rdb_netbuf_read_uint64(&p);
|
||||||
stats.m_entry_others = rdb_netbuf_read_uint64(&p);
|
stats.m_entry_others = rdb_netbuf_read_uint64(&p);
|
||||||
}
|
}
|
||||||
if (p+stats.m_distinct_keys_per_prefix.size()
|
if (p +
|
||||||
*sizeof(stats.m_distinct_keys_per_prefix[0]) > p2)
|
stats.m_distinct_keys_per_prefix.size() *
|
||||||
{
|
sizeof(stats.m_distinct_keys_per_prefix[0]) >
|
||||||
return 1;
|
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);
|
stats.m_distinct_keys_per_prefix[i] = rdb_netbuf_read_uint64(&p);
|
||||||
}
|
}
|
||||||
ret->push_back(stats);
|
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
|
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
|
for the index based on stats for each sst
|
||||||
*/
|
*/
|
||||||
void Rdb_index_stats::merge(
|
void Rdb_index_stats::merge(const Rdb_index_stats &s, const bool &increment,
|
||||||
const Rdb_index_stats& s, const bool &increment,
|
const int64_t &estimated_data_len) {
|
||||||
const int64_t &estimated_data_len)
|
|
||||||
{
|
|
||||||
std::size_t i;
|
std::size_t i;
|
||||||
|
|
||||||
DBUG_ASSERT(estimated_data_len >= 0);
|
DBUG_ASSERT(estimated_data_len >= 0);
|
||||||
|
|
||||||
m_gl_index_id = s.m_gl_index_id;
|
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());
|
m_distinct_keys_per_prefix.resize(s.m_distinct_keys_per_prefix.size());
|
||||||
}
|
}
|
||||||
if (increment)
|
if (increment) {
|
||||||
{
|
|
||||||
m_rows += s.m_rows;
|
m_rows += s.m_rows;
|
||||||
m_data_size += s.m_data_size;
|
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
|
we make a reasoned estimate for the data_file_length for the
|
||||||
index in the current SST.
|
index in the current SST.
|
||||||
*/
|
*/
|
||||||
m_actual_disk_size += s.m_actual_disk_size ? s.m_actual_disk_size :
|
m_actual_disk_size += s.m_actual_disk_size ? s.m_actual_disk_size
|
||||||
estimated_data_len * s.m_rows;
|
: estimated_data_len * s.m_rows;
|
||||||
m_entry_deletes += s.m_entry_deletes;
|
m_entry_deletes += s.m_entry_deletes;
|
||||||
m_entry_single_deletes += s.m_entry_single_deletes;
|
m_entry_single_deletes += s.m_entry_single_deletes;
|
||||||
m_entry_merges += s.m_entry_merges;
|
m_entry_merges += s.m_entry_merges;
|
||||||
m_entry_others += s.m_entry_others;
|
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];
|
m_distinct_keys_per_prefix[i] += s.m_distinct_keys_per_prefix[i];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
m_rows -= s.m_rows;
|
m_rows -= s.m_rows;
|
||||||
m_data_size -= s.m_data_size;
|
m_data_size -= s.m_data_size;
|
||||||
m_actual_disk_size -= s.m_actual_disk_size ? s.m_actual_disk_size :
|
m_actual_disk_size -= s.m_actual_disk_size ? s.m_actual_disk_size
|
||||||
estimated_data_len * s.m_rows;
|
: estimated_data_len * s.m_rows;
|
||||||
m_entry_deletes -= s.m_entry_deletes;
|
m_entry_deletes -= s.m_entry_deletes;
|
||||||
m_entry_single_deletes -= s.m_entry_single_deletes;
|
m_entry_single_deletes -= s.m_entry_single_deletes;
|
||||||
m_entry_merges -= s.m_entry_merges;
|
m_entry_merges -= s.m_entry_merges;
|
||||||
m_entry_others -= s.m_entry_others;
|
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];
|
m_distinct_keys_per_prefix[i] -= s.m_distinct_keys_per_prefix[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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 std::atomic<uint64_t> rocksdb_num_sst_entry_other;
|
||||||
extern my_bool rocksdb_compaction_sequential_deletes_count_sd;
|
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;
|
uint64_t m_deletes, m_window, m_file_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Rdb_index_stats {
|
||||||
struct Rdb_index_stats
|
|
||||||
{
|
|
||||||
enum {
|
enum {
|
||||||
INDEX_STATS_VERSION_INITIAL = 1,
|
INDEX_STATS_VERSION_INITIAL = 1,
|
||||||
INDEX_STATS_VERSION_ENTRY_TYPES = 2,
|
INDEX_STATS_VERSION_ENTRY_TYPES = 2,
|
||||||
@@ -66,54 +62,42 @@ struct Rdb_index_stats
|
|||||||
std::vector<Rdb_index_stats> *const ret);
|
std::vector<Rdb_index_stats> *const ret);
|
||||||
|
|
||||||
Rdb_index_stats() : Rdb_index_stats({0, 0}) {}
|
Rdb_index_stats() : Rdb_index_stats({0, 0}) {}
|
||||||
explicit Rdb_index_stats(GL_INDEX_ID gl_index_id) :
|
explicit Rdb_index_stats(GL_INDEX_ID gl_index_id)
|
||||||
m_gl_index_id(gl_index_id),
|
: m_gl_index_id(gl_index_id), m_data_size(0), m_rows(0),
|
||||||
m_data_size(0),
|
m_actual_disk_size(0), m_entry_deletes(0), m_entry_single_deletes(0),
|
||||||
m_rows(0),
|
m_entry_merges(0), m_entry_others(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,
|
void merge(const Rdb_index_stats &s, const bool &increment = true,
|
||||||
const int64_t &estimated_data_len = 0);
|
const int64_t &estimated_data_len = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector {
|
||||||
class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_tbl_prop_coll(
|
Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
|
||||||
Rdb_ddl_manager* const ddl_manager,
|
const Rdb_compact_params ¶ms, const uint32_t &cf_id,
|
||||||
const Rdb_compact_params ¶ms,
|
const uint8_t &table_stats_sampling_pct);
|
||||||
const uint32_t &cf_id,
|
|
||||||
const uint8_t &table_stats_sampling_pct
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Override parent class's virtual methods of interest.
|
Override parent class's virtual methods of interest.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual rocksdb::Status AddUserKey(
|
virtual rocksdb::Status AddUserKey(const rocksdb::Slice &key,
|
||||||
const rocksdb::Slice& key, const rocksdb::Slice& value,
|
const rocksdb::Slice &value,
|
||||||
rocksdb::EntryType type, rocksdb::SequenceNumber seq,
|
rocksdb::EntryType type,
|
||||||
|
rocksdb::SequenceNumber seq,
|
||||||
uint64_t file_size);
|
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 {
|
virtual const char *Name() const override { return "Rdb_tbl_prop_coll"; }
|
||||||
return "Rdb_tbl_prop_coll";
|
|
||||||
}
|
|
||||||
|
|
||||||
rocksdb::UserCollectedProperties GetReadableProperties() const override;
|
rocksdb::UserCollectedProperties GetReadableProperties() const override;
|
||||||
|
|
||||||
bool NeedCompact() const override;
|
bool NeedCompact() const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint64_t GetMaxDeletedRows() const {
|
uint64_t GetMaxDeletedRows() const { return m_max_deleted_rows; }
|
||||||
return m_max_deleted_rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_stats_from_tbl_props(
|
static void read_stats_from_tbl_props(
|
||||||
const std::shared_ptr<const rocksdb::TableProperties> &table_props,
|
const std::shared_ptr<const rocksdb::TableProperties> &table_props,
|
||||||
@@ -124,7 +108,8 @@ class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
|
|||||||
|
|
||||||
bool ShouldCollectStats();
|
bool ShouldCollectStats();
|
||||||
void CollectStatsForRow(const rocksdb::Slice &key,
|
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);
|
const uint64_t &file_size);
|
||||||
Rdb_index_stats *AccessStats(const rocksdb::Slice &key);
|
Rdb_index_stats *AccessStats(const rocksdb::Slice &key);
|
||||||
void AdjustDeletedRows(rocksdb::EntryType type);
|
void AdjustDeletedRows(rocksdb::EntryType type);
|
||||||
@@ -150,16 +135,15 @@ class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
|
|||||||
float m_card_adj_extra;
|
float m_card_adj_extra;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Rdb_tbl_prop_coll_factory
|
class Rdb_tbl_prop_coll_factory
|
||||||
: public rocksdb::TablePropertiesCollectorFactory {
|
: public rocksdb::TablePropertiesCollectorFactory {
|
||||||
public:
|
public:
|
||||||
Rdb_tbl_prop_coll_factory(const Rdb_tbl_prop_coll_factory &) = delete;
|
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)
|
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.
|
Override parent class's virtual methods of interest.
|
||||||
@@ -167,8 +151,8 @@ class Rdb_tbl_prop_coll_factory
|
|||||||
|
|
||||||
virtual rocksdb::TablePropertiesCollector *CreateTablePropertiesCollector(
|
virtual rocksdb::TablePropertiesCollector *CreateTablePropertiesCollector(
|
||||||
rocksdb::TablePropertiesCollectorFactory::Context context) override {
|
rocksdb::TablePropertiesCollectorFactory::Context context) override {
|
||||||
return new Rdb_tbl_prop_coll(
|
return new Rdb_tbl_prop_coll(m_ddl_manager, m_params,
|
||||||
m_ddl_manager, m_params, context.column_family_id,
|
context.column_family_id,
|
||||||
m_table_stats_sampling_pct);
|
m_table_stats_sampling_pct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,8 +28,7 @@ namespace myrocks {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
inline void rdb_netstr_append_uint64(my_core::String *const out_netstr,
|
inline void rdb_netstr_append_uint64(my_core::String *const out_netstr,
|
||||||
const uint64 &val)
|
const uint64 &val) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(out_netstr != nullptr);
|
DBUG_ASSERT(out_netstr != nullptr);
|
||||||
|
|
||||||
// Convert from host machine byte order (usually Little Endian) to network
|
// 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,
|
inline void rdb_netstr_append_uint32(my_core::String *const out_netstr,
|
||||||
const uint32 &val)
|
const uint32 &val) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(out_netstr != nullptr);
|
DBUG_ASSERT(out_netstr != nullptr);
|
||||||
|
|
||||||
// Convert from host machine byte order (usually Little Endian) to network
|
// 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,
|
inline void rdb_netstr_append_uint16(my_core::String *const out_netstr,
|
||||||
const uint16 &val)
|
const uint16 &val) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(out_netstr != nullptr);
|
DBUG_ASSERT(out_netstr != nullptr);
|
||||||
|
|
||||||
// Convert from host machine byte order (usually Little Endian) to network
|
// 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));
|
out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Basic network buffer ("netbuf") write helper functions.
|
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);
|
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||||
|
|
||||||
// Convert from host byte order (usually Little Endian) to network byte order
|
// 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));
|
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);
|
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||||
|
|
||||||
// Convert from host byte order (usually Little Endian) to network byte order
|
// 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));
|
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);
|
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||||
|
|
||||||
// Convert from host byte order (usually Little Endian) to network byte order
|
// 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));
|
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);
|
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||||
|
|
||||||
*dst_netbuf = c;
|
*dst_netbuf = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void rdb_netbuf_store_index(uchar *const dst_netbuf,
|
inline void rdb_netbuf_store_index(uchar *const dst_netbuf,
|
||||||
const uint32 &number)
|
const uint32 &number) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(dst_netbuf != nullptr);
|
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||||
|
|
||||||
rdb_netbuf_store_uint32(dst_netbuf, number);
|
rdb_netbuf_store_uint32(dst_netbuf, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Basic conversion helper functions from network byte order (Big Endian) to host
|
Basic conversion helper functions from network byte order (Big Endian) to host
|
||||||
machine byte order (usually Little Endian).
|
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);
|
DBUG_ASSERT(netbuf != nullptr);
|
||||||
|
|
||||||
uint64 net_val;
|
uint64 net_val;
|
||||||
@@ -128,8 +117,7 @@ inline uint64 rdb_netbuf_to_uint64(const uchar* const netbuf)
|
|||||||
return be64toh(net_val);
|
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);
|
DBUG_ASSERT(netbuf != nullptr);
|
||||||
|
|
||||||
uint32 net_val;
|
uint32 net_val;
|
||||||
@@ -140,8 +128,7 @@ inline uint32 rdb_netbuf_to_uint32(const uchar* const netbuf)
|
|||||||
return be32toh(net_val);
|
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);
|
DBUG_ASSERT(netbuf != nullptr);
|
||||||
|
|
||||||
uint16 net_val;
|
uint16 net_val;
|
||||||
@@ -152,14 +139,12 @@ inline uint16 rdb_netbuf_to_uint16(const uchar* const netbuf)
|
|||||||
return be16toh(net_val);
|
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);
|
DBUG_ASSERT(netbuf != nullptr);
|
||||||
|
|
||||||
return (uchar)netbuf[0];
|
return (uchar)netbuf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Basic network buffer ("netbuf") read helper functions.
|
Basic network buffer ("netbuf") read helper functions.
|
||||||
Network buffer stores data in Network Byte Order (Big Endian).
|
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.
|
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);
|
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||||
|
|
||||||
// Convert from network byte order (Big Endian) to host machine byte order
|
// 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;
|
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);
|
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||||
|
|
||||||
// Convert from network byte order (Big Endian) to host machine byte order
|
// 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;
|
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);
|
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||||
|
|
||||||
// Convert from network byte order (Big Endian) to host machine byte order
|
// 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,
|
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(gl_index_id != nullptr);
|
||||||
DBUG_ASSERT(netbuf_ptr != 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.
|
- it prevents one from reading beyond the end of the string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Rdb_string_reader
|
class Rdb_string_reader {
|
||||||
{
|
|
||||||
const char *m_ptr;
|
const char *m_ptr;
|
||||||
uint m_len;
|
uint m_len;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Rdb_string_reader &operator=(const Rdb_string_reader &) = default;
|
Rdb_string_reader &operator=(const Rdb_string_reader &) = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_string_reader(const Rdb_string_reader &) = default;
|
Rdb_string_reader(const Rdb_string_reader &) = default;
|
||||||
/* named constructor */
|
/* 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) {
|
if (!slice) {
|
||||||
return Rdb_string_reader("");
|
return Rdb_string_reader("");
|
||||||
} else {
|
} 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();
|
m_len = str.length();
|
||||||
if (m_len)
|
if (m_len) {
|
||||||
{
|
|
||||||
m_ptr = &str.at(0);
|
m_ptr = &str.at(0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
One can a create a Rdb_string_reader for reading from an empty string
|
One can a create a Rdb_string_reader for reading from an empty string
|
||||||
(although attempts to read anything will fail).
|
(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_ptr = slice->data();
|
||||||
m_len = slice->size();
|
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
|
Read the next @param size bytes. Returns pointer to the bytes read, or
|
||||||
nullptr if the remaining string doesn't have that many bytes.
|
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;
|
const char *res;
|
||||||
if (m_len < size)
|
if (m_len < size) {
|
||||||
{
|
|
||||||
res = nullptr;
|
res = nullptr;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
res = m_ptr;
|
res = m_ptr;
|
||||||
m_ptr += size;
|
m_ptr += size;
|
||||||
m_len -= size;
|
m_len -= size;
|
||||||
@@ -288,25 +260,21 @@ class Rdb_string_reader
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_uint8(uint* const res)
|
bool read_uint8(uint *const res) {
|
||||||
{
|
|
||||||
const uchar *p;
|
const uchar *p;
|
||||||
if (!(p = reinterpret_cast<const uchar *>(read(1))))
|
if (!(p = reinterpret_cast<const uchar *>(read(1))))
|
||||||
return true; // error
|
return true; // error
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
*res = *p;
|
*res = *p;
|
||||||
return false; // Ok
|
return false; // Ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_uint16(uint* const res)
|
bool read_uint16(uint *const res) {
|
||||||
{
|
|
||||||
const uchar *p;
|
const uchar *p;
|
||||||
if (!(p = reinterpret_cast<const uchar *>(read(2))))
|
if (!(p = reinterpret_cast<const uchar *>(read(2))))
|
||||||
return true; // error
|
return true; // error
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
*res = rdb_netbuf_to_uint16(p);
|
*res = rdb_netbuf_to_uint16(p);
|
||||||
return false; // Ok
|
return false; // Ok
|
||||||
}
|
}
|
||||||
@@ -322,7 +290,6 @@ class Rdb_string_reader
|
|||||||
const char *get_current_ptr() const { return m_ptr; }
|
const char *get_current_ptr() const { return m_ptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@brief
|
@brief
|
||||||
A buffer one can write the data to.
|
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;
|
std::vector<uchar> m_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_string_writer(const Rdb_string_writer &) = delete;
|
Rdb_string_writer(const Rdb_string_writer &) = delete;
|
||||||
Rdb_string_writer &operator=(const Rdb_string_writer &) = delete;
|
Rdb_string_writer &operator=(const Rdb_string_writer &) = delete;
|
||||||
Rdb_string_writer() = default;
|
Rdb_string_writer() = default;
|
||||||
|
|
||||||
void clear() { m_data.clear(); }
|
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));
|
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();
|
const auto size = m_data.size();
|
||||||
m_data.resize(size + 2);
|
m_data.resize(size + 2);
|
||||||
rdb_netbuf_store_uint16(m_data.data() + size, val);
|
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();
|
const auto size = m_data.size();
|
||||||
m_data.resize(size + 4);
|
m_data.resize(size + 4);
|
||||||
rdb_netbuf_store_uint32(m_data.data() + size, val);
|
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);
|
DBUG_ASSERT(new_data != nullptr);
|
||||||
m_data.insert(m_data.end(), new_data, new_data + len);
|
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(); }
|
uchar *ptr() { return m_data.data(); }
|
||||||
size_t get_current_pos() const { return m_data.size(); }
|
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
|
// This function will only overwrite what was written
|
||||||
DBUG_ASSERT(pos < get_current_pos());
|
DBUG_ASSERT(pos < get_current_pos());
|
||||||
m_data.data()[pos] = new_val;
|
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
|
// This function will only overwrite what was written
|
||||||
DBUG_ASSERT(pos < get_current_pos() && (pos + 1) < get_current_pos());
|
DBUG_ASSERT(pos < get_current_pos() && (pos + 1) < get_current_pos());
|
||||||
rdb_netbuf_store_uint16(m_data.data() + pos, new_val);
|
rdb_netbuf_store_uint16(m_data.data() + pos, new_val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A helper class for writing bits into Rdb_string_writer.
|
A helper class for writing bits into Rdb_string_writer.
|
||||||
|
|
||||||
The class assumes (but doesn't check) that nobody tries to write
|
The class assumes (but doesn't check) that nobody tries to write
|
||||||
anything to the Rdb_string_writer that it is writing to.
|
anything to the Rdb_string_writer that it is writing to.
|
||||||
*/
|
*/
|
||||||
class Rdb_bit_writer
|
class Rdb_bit_writer {
|
||||||
{
|
|
||||||
Rdb_string_writer *m_writer;
|
Rdb_string_writer *m_writer;
|
||||||
uchar m_offset;
|
uchar m_offset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_bit_writer(const Rdb_bit_writer &) = delete;
|
Rdb_bit_writer(const Rdb_bit_writer &) = delete;
|
||||||
Rdb_bit_writer &operator=(const Rdb_bit_writer &) = delete;
|
Rdb_bit_writer &operator=(const Rdb_bit_writer &) = delete;
|
||||||
|
|
||||||
explicit Rdb_bit_writer(Rdb_string_writer *writer_arg)
|
explicit Rdb_bit_writer(Rdb_string_writer *writer_arg)
|
||||||
: m_writer(writer_arg),
|
: m_writer(writer_arg), m_offset(0) {}
|
||||||
m_offset(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint size, const uint &value)
|
void write(uint size, const uint &value) {
|
||||||
{
|
|
||||||
DBUG_ASSERT((value & ((1 << size) - 1)) == value);
|
DBUG_ASSERT((value & ((1 << size) - 1)) == value);
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0) {
|
||||||
{
|
if (m_offset == 0) {
|
||||||
if (m_offset == 0)
|
|
||||||
{
|
|
||||||
m_writer->write_uint8(0);
|
m_writer->write_uint8(0);
|
||||||
}
|
}
|
||||||
// number of bits to put in this byte
|
// number of bits to put in this byte
|
||||||
const uint bits = std::min(size, (uint)(8 - m_offset));
|
const uint bits = std::min(size, (uint)(8 - m_offset));
|
||||||
uchar* const last_byte= m_writer->ptr() + m_writer->get_current_pos() - 1;
|
uchar *const last_byte =
|
||||||
*last_byte |=
|
m_writer->ptr() + m_writer->get_current_pos() - 1;
|
||||||
(uchar) ((value >> (size - bits)) & ((1 << bits) - 1)) << m_offset;
|
*last_byte |= (uchar)((value >> (size - bits)) & ((1 << bits) - 1))
|
||||||
|
<< m_offset;
|
||||||
size -= bits;
|
size -= bits;
|
||||||
m_offset = (m_offset + bits) & 0x7;
|
m_offset = (m_offset + bits) & 0x7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Rdb_bit_reader
|
class Rdb_bit_reader {
|
||||||
{
|
|
||||||
const uchar *m_cur;
|
const uchar *m_cur;
|
||||||
uchar m_offset;
|
uchar m_offset;
|
||||||
uint m_ret;
|
uint m_ret;
|
||||||
Rdb_string_reader *const m_reader;
|
Rdb_string_reader *const m_reader;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_bit_reader(const Rdb_bit_reader &) = delete;
|
Rdb_bit_reader(const Rdb_bit_reader &) = delete;
|
||||||
Rdb_bit_reader &operator=(const Rdb_bit_reader &) = delete;
|
Rdb_bit_reader &operator=(const Rdb_bit_reader &) = delete;
|
||||||
|
|
||||||
explicit Rdb_bit_reader(Rdb_string_reader *const reader)
|
explicit Rdb_bit_reader(Rdb_string_reader *const reader)
|
||||||
: m_cur(nullptr),
|
: m_cur(nullptr), m_offset(0), m_reader(reader) {}
|
||||||
m_offset(0),
|
|
||||||
m_reader(reader)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a pointer to an uint containing the bits read. On subsequent
|
// Returns a pointer to an uint containing the bits read. On subsequent
|
||||||
// reads, the value being pointed to will be overwritten. Returns nullptr
|
// reads, the value being pointed to will be overwritten. Returns nullptr
|
||||||
// on failure.
|
// on failure.
|
||||||
uint *read(uint size)
|
uint *read(uint size) {
|
||||||
{
|
|
||||||
m_ret = 0;
|
m_ret = 0;
|
||||||
DBUG_ASSERT(size <= 32);
|
DBUG_ASSERT(size <= 32);
|
||||||
|
|
||||||
while (size > 0)
|
while (size > 0) {
|
||||||
{
|
if (m_offset == 0) {
|
||||||
if (m_offset == 0)
|
|
||||||
{
|
|
||||||
m_cur = (const uchar *)m_reader->read(1);
|
m_cur = (const uchar *)m_reader->read(1);
|
||||||
if (m_cur == nullptr)
|
if (m_cur == nullptr) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,8 +28,7 @@
|
|||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
/* Check if ColumnFamily name says it's a reverse-ordered CF */
|
/* 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
|
/* nullptr means the default CF is used.. (TODO: can the default CF be
|
||||||
* reverse?) */
|
* reverse?) */
|
||||||
if (name && !strncmp(name, "rev:", 4))
|
if (name && !strncmp(name, "rev:", 4))
|
||||||
@@ -44,8 +43,7 @@ static PSI_mutex_key ex_key_cfm;
|
|||||||
|
|
||||||
void Rdb_cf_manager::init(
|
void Rdb_cf_manager::init(
|
||||||
Rdb_cf_options *const cf_options,
|
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);
|
mysql_mutex_init(ex_key_cfm, &m_mutex, MY_MUTEX_INIT_FAST);
|
||||||
|
|
||||||
DBUG_ASSERT(cf_options != nullptr);
|
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) {
|
for (auto it : m_cf_name_map) {
|
||||||
delete it.second;
|
delete it.second;
|
||||||
}
|
}
|
||||||
mysql_mutex_destroy(&m_mutex);
|
mysql_mutex_destroy(&m_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Generate Column Family name for per-index column families
|
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,
|
void Rdb_cf_manager::get_per_index_cf_name(const std::string &db_table_name,
|
||||||
const char *const index_name,
|
const char *const index_name,
|
||||||
std::string* const res)
|
std::string *const res) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(index_name != nullptr);
|
DBUG_ASSERT(index_name != nullptr);
|
||||||
DBUG_ASSERT(res != nullptr);
|
DBUG_ASSERT(res != nullptr);
|
||||||
|
|
||||||
*res = db_table_name + "." + index_name;
|
*res = db_table_name + "." + index_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@brief
|
@brief
|
||||||
Find column family by name. If it doesn't exist, create it
|
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
|
See Rdb_cf_manager::get_cf
|
||||||
*/
|
*/
|
||||||
rocksdb::ColumnFamilyHandle *
|
rocksdb::ColumnFamilyHandle *
|
||||||
Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
|
Rdb_cf_manager::get_or_create_cf(rocksdb::DB *const rdb, const char *cf_name,
|
||||||
const char *cf_name,
|
|
||||||
const std::string &db_table_name,
|
const std::string &db_table_name,
|
||||||
const char *const index_name,
|
const char *const index_name,
|
||||||
bool* const is_automatic)
|
bool *const is_automatic) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(rdb != nullptr);
|
DBUG_ASSERT(rdb != nullptr);
|
||||||
DBUG_ASSERT(is_automatic != 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;
|
cf_name = DEFAULT_CF_NAME;
|
||||||
|
|
||||||
std::string per_index_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);
|
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
|
||||||
cf_name = per_index_name.c_str();
|
cf_name = per_index_name.c_str();
|
||||||
*is_automatic = true;
|
*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);
|
const auto it = m_cf_name_map.find(cf_name);
|
||||||
if (it != m_cf_name_map.end())
|
if (it != m_cf_name_map.end())
|
||||||
cf_handle = it->second;
|
cf_handle = it->second;
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
/* Create a Column Family. */
|
/* Create a Column Family. */
|
||||||
const std::string cf_name_str(cf_name);
|
const std::string cf_name_str(cf_name);
|
||||||
rocksdb::ColumnFamilyOptions opts;
|
rocksdb::ColumnFamilyOptions opts;
|
||||||
m_cf_options->get_cf_options(cf_name_str, &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(" write_buffer_size=%ld", opts.write_buffer_size);
|
||||||
sql_print_information(" target_file_size_base=%" PRIu64,
|
sql_print_information(" target_file_size_base=%" PRIu64,
|
||||||
opts.target_file_size_base);
|
opts.target_file_size_base);
|
||||||
@@ -149,7 +139,6 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
|
|||||||
return cf_handle;
|
return cf_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find column family by its cf_name.
|
Find column family by its cf_name.
|
||||||
|
|
||||||
@@ -163,11 +152,9 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
rocksdb::ColumnFamilyHandle *
|
rocksdb::ColumnFamilyHandle *
|
||||||
Rdb_cf_manager::get_cf(const char *cf_name,
|
Rdb_cf_manager::get_cf(const char *cf_name, const std::string &db_table_name,
|
||||||
const std::string& db_table_name,
|
|
||||||
const char *const index_name,
|
const char *const index_name,
|
||||||
bool* const is_automatic) const
|
bool *const is_automatic) const {
|
||||||
{
|
|
||||||
DBUG_ASSERT(is_automatic != nullptr);
|
DBUG_ASSERT(is_automatic != nullptr);
|
||||||
|
|
||||||
rocksdb::ColumnFamilyHandle *cf_handle;
|
rocksdb::ColumnFamilyHandle *cf_handle;
|
||||||
@@ -178,8 +165,7 @@ Rdb_cf_manager::get_cf(const char *cf_name,
|
|||||||
cf_name = DEFAULT_CF_NAME;
|
cf_name = DEFAULT_CF_NAME;
|
||||||
|
|
||||||
std::string per_index_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);
|
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
|
||||||
cf_name = per_index_name.c_str();
|
cf_name = per_index_name.c_str();
|
||||||
*is_automatic = true;
|
*is_automatic = true;
|
||||||
@@ -193,8 +179,7 @@ Rdb_cf_manager::get_cf(const char *cf_name,
|
|||||||
return cf_handle;
|
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;
|
rocksdb::ColumnFamilyHandle *cf_handle = nullptr;
|
||||||
|
|
||||||
mysql_mutex_lock(&m_mutex);
|
mysql_mutex_lock(&m_mutex);
|
||||||
@@ -206,9 +191,7 @@ rocksdb::ColumnFamilyHandle* Rdb_cf_manager::get_cf(const uint32_t &id) const
|
|||||||
return cf_handle;
|
return cf_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string> Rdb_cf_manager::get_cf_names(void) const {
|
||||||
Rdb_cf_manager::get_cf_names(void) const
|
|
||||||
{
|
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
|
|
||||||
mysql_mutex_lock(&m_mutex);
|
mysql_mutex_lock(&m_mutex);
|
||||||
@@ -220,8 +203,7 @@ Rdb_cf_manager::get_cf_names(void) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rocksdb::ColumnFamilyHandle *>
|
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;
|
std::vector<rocksdb::ColumnFamilyHandle *> list;
|
||||||
|
|
||||||
mysql_mutex_lock(&m_mutex);
|
mysql_mutex_lock(&m_mutex);
|
||||||
|
@@ -46,15 +46,13 @@ namespace myrocks {
|
|||||||
- CFs are created in a synchronized way. We can't remove them, yet.
|
- 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<std::string, rocksdb::ColumnFamilyHandle *> m_cf_name_map;
|
||||||
std::map<uint32_t, rocksdb::ColumnFamilyHandle *> m_cf_id_map;
|
std::map<uint32_t, rocksdb::ColumnFamilyHandle *> m_cf_id_map;
|
||||||
|
|
||||||
mutable mysql_mutex_t m_mutex;
|
mutable mysql_mutex_t m_mutex;
|
||||||
|
|
||||||
static
|
static void get_per_index_cf_name(const std::string &db_table_name,
|
||||||
void get_per_index_cf_name(const std::string& db_table_name,
|
|
||||||
const char *const index_name,
|
const char *const index_name,
|
||||||
std::string *const res);
|
std::string *const res);
|
||||||
|
|
||||||
@@ -68,7 +66,8 @@ public:
|
|||||||
static bool is_cf_name_reverse(const char *const name);
|
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.
|
families that are present in the database. The first CF is the default CF.
|
||||||
*/
|
*/
|
||||||
void init(Rdb_cf_options *cf_options,
|
void init(Rdb_cf_options *cf_options,
|
||||||
@@ -80,10 +79,10 @@ public:
|
|||||||
- cf_name=nullptr means use default column family
|
- cf_name=nullptr means use default column family
|
||||||
- cf_name=_auto_ means use 'dbname.tablename.indexname'
|
- cf_name=_auto_ means use 'dbname.tablename.indexname'
|
||||||
*/
|
*/
|
||||||
rocksdb::ColumnFamilyHandle* get_or_create_cf(
|
rocksdb::ColumnFamilyHandle *
|
||||||
rocksdb::DB* const rdb, const char *cf_name,
|
get_or_create_cf(rocksdb::DB *const rdb, const char *cf_name,
|
||||||
const std::string& db_table_name, const char* const index_name,
|
const std::string &db_table_name,
|
||||||
bool* const is_automatic);
|
const char *const index_name, bool *const is_automatic);
|
||||||
|
|
||||||
/* Used by table open */
|
/* Used by table open */
|
||||||
rocksdb::ColumnFamilyHandle *get_cf(const char *cf_name,
|
rocksdb::ColumnFamilyHandle *get_cf(const char *cf_name,
|
||||||
@@ -102,9 +101,9 @@ public:
|
|||||||
|
|
||||||
// void drop_cf(); -- not implemented so far.
|
// void drop_cf(); -- not implemented so far.
|
||||||
|
|
||||||
void get_cf_options(
|
void get_cf_options(const std::string &cf_name,
|
||||||
const std::string &cf_name,
|
rocksdb::ColumnFamilyOptions *const opts)
|
||||||
rocksdb::ColumnFamilyOptions* const opts) __attribute__((__nonnull__)) {
|
MY_ATTRIBUTE((__nonnull__)) {
|
||||||
m_cf_options->get_cf_options(cf_name, opts);
|
m_cf_options->get_cf_options(cf_name, opts);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -44,8 +44,7 @@ bool Rdb_cf_options::init(
|
|||||||
const rocksdb::BlockBasedTableOptions &table_options,
|
const rocksdb::BlockBasedTableOptions &table_options,
|
||||||
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
|
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
|
||||||
const char *const default_cf_options,
|
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(default_cf_options != nullptr);
|
||||||
DBUG_ASSERT(override_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,
|
void Rdb_cf_options::get(const std::string &cf_name,
|
||||||
rocksdb::ColumnFamilyOptions* const opts)
|
rocksdb::ColumnFamilyOptions *const opts) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(opts != nullptr);
|
DBUG_ASSERT(opts != nullptr);
|
||||||
|
|
||||||
// set defaults
|
// set defaults
|
||||||
rocksdb::GetColumnFamilyOptionsFromString(*opts,
|
rocksdb::GetColumnFamilyOptionsFromString(*opts, m_default_config, opts);
|
||||||
m_default_config,
|
|
||||||
opts);
|
|
||||||
|
|
||||||
// set per-cf config if we have one
|
// set per-cf config if we have one
|
||||||
Name_to_config_t::iterator it = m_name_map.find(cf_name);
|
Name_to_config_t::iterator it = m_name_map.find(cf_name);
|
||||||
if (it != m_name_map.end()) {
|
if (it != m_name_map.end()) {
|
||||||
rocksdb::GetColumnFamilyOptionsFromString(*opts,
|
rocksdb::GetColumnFamilyOptionsFromString(*opts, it->second, 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;
|
rocksdb::ColumnFamilyOptions options;
|
||||||
|
|
||||||
if (!default_config.empty() &&
|
if (!default_config.empty() &&
|
||||||
!rocksdb::GetColumnFamilyOptionsFromString(options,
|
!rocksdb::GetColumnFamilyOptionsFromString(options, default_config,
|
||||||
default_config,
|
&options)
|
||||||
&options).ok()) {
|
.ok()) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "Invalid default column family config: %s\n",
|
||||||
"Invalid default column family config: %s\n",
|
|
||||||
default_config.c_str());
|
default_config.c_str());
|
||||||
return false;
|
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.
|
// 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);
|
DBUG_ASSERT(pos != nullptr);
|
||||||
|
|
||||||
while (*pos < input.size() && isspace(input[*pos]))
|
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.
|
// the beginning and end but are not removed between other characters.
|
||||||
bool Rdb_cf_options::find_column_family(const std::string &input,
|
bool Rdb_cf_options::find_column_family(const std::string &input,
|
||||||
size_t *const pos,
|
size_t *const pos,
|
||||||
std::string* const key)
|
std::string *const key) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(pos != nullptr);
|
DBUG_ASSERT(pos != nullptr);
|
||||||
DBUG_ASSERT(key != 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;
|
size_t end_pos = *pos - 1;
|
||||||
|
|
||||||
// Loop through the characters in the string until we see a '='.
|
// 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 this is not a space, move the end position to the current position.
|
||||||
if (input[*pos] != ' ')
|
if (input[*pos] != ' ')
|
||||||
end_pos = *pos;
|
end_pos = *pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end_pos == beg_pos - 1)
|
if (end_pos == beg_pos - 1) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning("No column family found (options: %s)", input.c_str());
|
sql_print_warning("No column family found (options: %s)", input.c_str());
|
||||||
return false;
|
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
|
// portion until we hit as many close curly braces as we have seen open curly
|
||||||
// braces.
|
// braces.
|
||||||
bool Rdb_cf_options::find_options(const std::string &input, size_t *const pos,
|
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(pos != nullptr);
|
||||||
DBUG_ASSERT(options != nullptr);
|
DBUG_ASSERT(options != nullptr);
|
||||||
|
|
||||||
// Make sure we have an open curly brace at the current position.
|
// 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
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning("Invalid cf options, '{' expected (options: %s)",
|
sql_print_warning("Invalid cf options, '{' expected (options: %s)",
|
||||||
input.c_str());
|
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
|
// Loop through the characters in the string until we find the appropriate
|
||||||
// number of closing curly braces.
|
// number of closing curly braces.
|
||||||
while (*pos < input.size())
|
while (*pos < input.size()) {
|
||||||
{
|
switch (input[*pos]) {
|
||||||
switch (input[*pos])
|
|
||||||
{
|
|
||||||
case '}':
|
case '}':
|
||||||
// If this is a closing curly brace and we bring the count down to zero
|
// 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.
|
// 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);
|
*options = input.substr(beg_pos, *pos - beg_pos);
|
||||||
++(*pos); // Move past the last closing curly brace
|
++(*pos); // Move past the last closing curly brace
|
||||||
return true;
|
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,
|
bool Rdb_cf_options::find_cf_options_pair(const std::string &input,
|
||||||
size_t *const pos,
|
size_t *const pos,
|
||||||
std::string *const cf,
|
std::string *const cf,
|
||||||
std::string* const opt_str)
|
std::string *const opt_str) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(pos != nullptr);
|
DBUG_ASSERT(pos != nullptr);
|
||||||
DBUG_ASSERT(cf != nullptr);
|
DBUG_ASSERT(cf != nullptr);
|
||||||
DBUG_ASSERT(opt_str != nullptr);
|
DBUG_ASSERT(opt_str != nullptr);
|
||||||
@@ -229,8 +211,7 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we are at the end of the input then we generate an error.
|
// 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
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning("Invalid cf options, '=' expected (options: %s)",
|
sql_print_warning("Invalid cf options, '=' expected (options: %s)",
|
||||||
input.c_str());
|
input.c_str());
|
||||||
@@ -250,10 +231,8 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
|||||||
skip_spaces(input, pos);
|
skip_spaces(input, pos);
|
||||||
|
|
||||||
// We should either be at the end of the input string or at a semicolon.
|
// We should either be at the end of the input string or at a semicolon.
|
||||||
if (*pos < input.size())
|
if (*pos < input.size()) {
|
||||||
{
|
if (input[*pos] != ';') {
|
||||||
if (input[*pos] != ';')
|
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning("Invalid cf options, ';' expected (options: %s)",
|
sql_print_warning("Invalid cf options, ';' expected (options: %s)",
|
||||||
input.c_str());
|
input.c_str());
|
||||||
@@ -266,8 +245,7 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
|||||||
return true;
|
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?
|
// TODO(???): support updates?
|
||||||
|
|
||||||
std::string cf;
|
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.
|
// Loop through the characters of the string until we reach the end.
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while (pos < override_config.size())
|
while (pos < override_config.size()) {
|
||||||
{
|
|
||||||
// Attempt to find <cf>={<opt_str>}.
|
// Attempt to find <cf>={<opt_str>}.
|
||||||
if (!find_cf_options_pair(override_config, &pos, &cf, &opt_str))
|
if (!find_cf_options_pair(override_config, &pos, &cf, &opt_str))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Generate an error if we have already seen this column family.
|
// 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
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning(
|
sql_print_warning(
|
||||||
"Duplicate entry for %s in override options (options: %s)",
|
"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.
|
// Generate an error if the <opt_str> is not valid according to RocksDB.
|
||||||
if (!rocksdb::GetColumnFamilyOptionsFromString(
|
if (!rocksdb::GetColumnFamilyOptionsFromString(options, opt_str, &options)
|
||||||
options, opt_str, &options).ok())
|
.ok()) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning(
|
sql_print_warning(
|
||||||
"Invalid cf config for %s in override options (options: %s)",
|
"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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rocksdb::Comparator* Rdb_cf_options::get_cf_comparator(
|
const rocksdb::Comparator *
|
||||||
const std::string& cf_name)
|
Rdb_cf_options::get_cf_comparator(const std::string &cf_name) {
|
||||||
{
|
if (Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str())) {
|
||||||
if (Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str()))
|
|
||||||
{
|
|
||||||
return &s_rev_pk_comparator;
|
return &s_rev_pk_comparator;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return &s_pk_comparator;
|
return &s_pk_comparator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rdb_cf_options::get_cf_options(const std::string &cf_name,
|
void Rdb_cf_options::get_cf_options(const std::string &cf_name,
|
||||||
rocksdb::ColumnFamilyOptions* const opts)
|
rocksdb::ColumnFamilyOptions *const opts) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(opts != nullptr);
|
DBUG_ASSERT(opts != nullptr);
|
||||||
|
|
||||||
*opts = m_default_cf_opts;
|
*opts = m_default_cf_opts;
|
||||||
|
@@ -38,18 +38,18 @@ namespace myrocks {
|
|||||||
and also there is a default value which applies to column
|
and also there is a default value which applies to column
|
||||||
families not found in the map.
|
families not found in the map.
|
||||||
*/
|
*/
|
||||||
class Rdb_cf_options
|
class Rdb_cf_options {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_cf_options(const Rdb_cf_options &) = delete;
|
Rdb_cf_options(const Rdb_cf_options &) = delete;
|
||||||
Rdb_cf_options &operator=(const Rdb_cf_options &) = delete;
|
Rdb_cf_options &operator=(const Rdb_cf_options &) = delete;
|
||||||
Rdb_cf_options() = default;
|
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(
|
bool init(const rocksdb::BlockBasedTableOptions &table_options,
|
||||||
const rocksdb::BlockBasedTableOptions& table_options,
|
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory>
|
||||||
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
|
prop_coll_factory,
|
||||||
const char *const default_cf_options,
|
const char *const default_cf_options,
|
||||||
const char *const override_cf_options);
|
const char *const override_cf_options);
|
||||||
|
|
||||||
@@ -57,12 +57,12 @@ class Rdb_cf_options
|
|||||||
return m_default_cf_opts;
|
return m_default_cf_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const rocksdb::Comparator* get_cf_comparator(
|
static const rocksdb::Comparator *
|
||||||
const std::string& cf_name);
|
get_cf_comparator(const std::string &cf_name);
|
||||||
|
|
||||||
void get_cf_options(
|
void get_cf_options(const std::string &cf_name,
|
||||||
const std::string &cf_name,
|
rocksdb::ColumnFamilyOptions *const opts)
|
||||||
rocksdb::ColumnFamilyOptions* const opts) __attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool set_default(const std::string &default_config);
|
bool set_default(const std::string &default_config);
|
||||||
|
@@ -32,8 +32,7 @@
|
|||||||
|
|
||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
class Rdb_compact_filter : public rocksdb::CompactionFilter
|
class Rdb_compact_filter : public rocksdb::CompactionFilter {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_compact_filter(const Rdb_compact_filter &) = delete;
|
Rdb_compact_filter(const Rdb_compact_filter &) = delete;
|
||||||
Rdb_compact_filter &operator=(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).
|
// V1 Filter is thread safe on our usage (creating from Factory).
|
||||||
// Make sure to protect instance variables when switching to thread
|
// Make sure to protect instance variables when switching to thread
|
||||||
// unsafe in the future.
|
// unsafe in the future.
|
||||||
virtual bool Filter(int level,
|
virtual bool Filter(int level, const rocksdb::Slice &key,
|
||||||
const rocksdb::Slice& key,
|
|
||||||
const rocksdb::Slice &existing_value,
|
const rocksdb::Slice &existing_value,
|
||||||
std::string *new_value,
|
std::string *new_value,
|
||||||
bool* value_changed) const override
|
bool *value_changed) const override {
|
||||||
{
|
|
||||||
DBUG_ASSERT(key.size() >= sizeof(uint32));
|
DBUG_ASSERT(key.size() >= sizeof(uint32));
|
||||||
|
|
||||||
GL_INDEX_ID gl_index_id;
|
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 (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_num_deleted = 0;
|
||||||
}
|
}
|
||||||
m_should_delete =
|
m_should_delete =
|
||||||
@@ -69,8 +65,7 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
|
|||||||
m_prev_index = gl_index_id;
|
m_prev_index = gl_index_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_should_delete)
|
if (m_should_delete) {
|
||||||
{
|
|
||||||
m_num_deleted++;
|
m_num_deleted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,10 +74,7 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
|
|||||||
|
|
||||||
virtual bool IgnoreSnapshots() const override { return true; }
|
virtual bool IgnoreSnapshots() const override { return true; }
|
||||||
|
|
||||||
virtual const char* Name() const override
|
virtual const char *Name() const override { return "Rdb_compact_filter"; }
|
||||||
{
|
|
||||||
return "Rdb_compact_filter";
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Column family for this compaction filter
|
// Column family for this compaction filter
|
||||||
@@ -95,23 +87,19 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
|
|||||||
mutable bool m_should_delete = false;
|
mutable bool m_should_delete = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Rdb_compact_filter_factory : public rocksdb::CompactionFilterFactory
|
class Rdb_compact_filter_factory : public rocksdb::CompactionFilterFactory {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_compact_filter_factory(const Rdb_compact_filter_factory &) = delete;
|
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() {}
|
||||||
|
|
||||||
~Rdb_compact_filter_factory() {}
|
~Rdb_compact_filter_factory() {}
|
||||||
|
|
||||||
const char* Name() const override
|
const char *Name() const override { return "Rdb_compact_filter_factory"; }
|
||||||
{
|
|
||||||
return "Rdb_compact_filter_factory";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<rocksdb::CompactionFilter> CreateCompactionFilter(
|
std::unique_ptr<rocksdb::CompactionFilter> CreateCompactionFilter(
|
||||||
const rocksdb::CompactionFilter::Context& context) override
|
const rocksdb::CompactionFilter::Context &context) override {
|
||||||
{
|
|
||||||
return std::unique_ptr<rocksdb::CompactionFilter>(
|
return std::unique_ptr<rocksdb::CompactionFilter>(
|
||||||
new Rdb_compact_filter(context.column_family_id));
|
new Rdb_compact_filter(context.column_family_id));
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
/* RocksDB header files */
|
/* RocksDB header files */
|
||||||
#include "rocksdb/comparator.h"
|
#include "rocksdb/comparator.h"
|
||||||
|
|
||||||
|
/* MyRocks header files */
|
||||||
|
#include "./rdb_utils.h"
|
||||||
|
|
||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -32,15 +35,14 @@ namespace myrocks {
|
|||||||
(todo: knowledge about this format is shared between this class and
|
(todo: knowledge about this format is shared between this class and
|
||||||
Rdb_key_def)
|
Rdb_key_def)
|
||||||
*/
|
*/
|
||||||
class Rdb_pk_comparator : public rocksdb::Comparator
|
class Rdb_pk_comparator : public rocksdb::Comparator {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_pk_comparator(const Rdb_pk_comparator &) = delete;
|
Rdb_pk_comparator(const Rdb_pk_comparator &) = delete;
|
||||||
Rdb_pk_comparator &operator=(const Rdb_pk_comparator &) = delete;
|
Rdb_pk_comparator &operator=(const Rdb_pk_comparator &) = delete;
|
||||||
Rdb_pk_comparator() = default;
|
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 a_size = a.size();
|
||||||
const size_t b_size = b.size();
|
const size_t b_size = b.size();
|
||||||
const size_t len = (a_size < b_size) ? a_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;
|
return res;
|
||||||
|
|
||||||
/* Ok, res== 0 */
|
/* Ok, res== 0 */
|
||||||
if (a_size != b_size)
|
if (a_size != b_size) {
|
||||||
{
|
|
||||||
return a_size < b_size ? -1 : 1;
|
return a_size < b_size ? -1 : 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Override virtual methods of interest */
|
/* 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);
|
return bytewise_compare(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,20 +76,18 @@ class Rdb_pk_comparator : public rocksdb::Comparator
|
|||||||
void FindShortSuccessor(std::string *key) const override {}
|
void FindShortSuccessor(std::string *key) const override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Rdb_rev_comparator : public rocksdb::Comparator
|
class Rdb_rev_comparator : public rocksdb::Comparator {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_rev_comparator(const Rdb_rev_comparator &) = delete;
|
Rdb_rev_comparator(const Rdb_rev_comparator &) = delete;
|
||||||
Rdb_rev_comparator &operator=(const Rdb_rev_comparator &) = delete;
|
Rdb_rev_comparator &operator=(const Rdb_rev_comparator &) = delete;
|
||||||
Rdb_rev_comparator() = default;
|
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);
|
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);
|
return -Rdb_pk_comparator::bytewise_compare(a, b);
|
||||||
}
|
}
|
||||||
const char *Name() const override { return "rev:RocksDB_SE_v3.10"; }
|
const char *Name() const override { return "rev:RocksDB_SE_v3.10"; }
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -56,15 +56,13 @@ class Rdb_ddl_manager;
|
|||||||
In order to accommodate both cases, we require both calls to be made and
|
In order to accommodate both cases, we require both calls to be made and
|
||||||
unpack_info is passed as context data between the two.
|
unpack_info is passed as context data between the two.
|
||||||
*/
|
*/
|
||||||
class Rdb_pack_field_context
|
class Rdb_pack_field_context {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_pack_field_context(const Rdb_pack_field_context &) = delete;
|
Rdb_pack_field_context(const Rdb_pack_field_context &) = delete;
|
||||||
Rdb_pack_field_context &operator=(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) :
|
explicit Rdb_pack_field_context(Rdb_string_writer *const writer_arg)
|
||||||
writer(writer_arg)
|
: writer(writer_arg) {}
|
||||||
{}
|
|
||||||
|
|
||||||
// NULL means we're not producing unpack_info.
|
// NULL means we're not producing unpack_info.
|
||||||
Rdb_string_writer *writer;
|
Rdb_string_writer *writer;
|
||||||
@@ -113,14 +111,13 @@ const char RDB_CHECKSUM_DATA_TAG= 0x01;
|
|||||||
*/
|
*/
|
||||||
const char RDB_UNPACK_DATA_TAG = 0x02;
|
const char RDB_UNPACK_DATA_TAG = 0x02;
|
||||||
const size_t RDB_UNPACK_DATA_LEN_SIZE = sizeof(uint16_t);
|
const size_t RDB_UNPACK_DATA_LEN_SIZE = sizeof(uint16_t);
|
||||||
const size_t RDB_UNPACK_HEADER_SIZE= sizeof(RDB_UNPACK_DATA_TAG) +
|
const size_t RDB_UNPACK_HEADER_SIZE =
|
||||||
RDB_UNPACK_DATA_LEN_SIZE;
|
sizeof(RDB_UNPACK_DATA_TAG) + RDB_UNPACK_DATA_LEN_SIZE;
|
||||||
|
|
||||||
// Possible return values for rdb_index_field_unpack_t functions.
|
// Possible return values for rdb_index_field_unpack_t functions.
|
||||||
enum {
|
enum {
|
||||||
UNPACK_SUCCESS = 0,
|
UNPACK_SUCCESS = 0,
|
||||||
UNPACK_FAILURE = 1,
|
UNPACK_FAILURE = 1,
|
||||||
UNPACK_INFO_MISSING= 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -163,19 +160,16 @@ enum {
|
|||||||
reads.
|
reads.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Rdb_key_def
|
class Rdb_key_def {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/* Convert a key from KeyTupleFormat to mem-comparable form */
|
/* Convert a key from KeyTupleFormat to mem-comparable form */
|
||||||
uint pack_index_tuple(TABLE *const tbl, uchar *const pack_buffer,
|
uint pack_index_tuple(TABLE *const tbl, uchar *const pack_buffer,
|
||||||
uchar* const packed_tuple,
|
uchar *const packed_tuple, const uchar *const key_tuple,
|
||||||
const uchar* const key_tuple,
|
|
||||||
const key_part_map &keypart_map) const;
|
const key_part_map &keypart_map) const;
|
||||||
|
|
||||||
/* Convert a key from Table->record format to mem-comparable form */
|
/* Convert a key from Table->record format to mem-comparable form */
|
||||||
uint pack_record(const TABLE *const tbl, uchar *const pack_buffer,
|
uint pack_record(const TABLE *const tbl, uchar *const pack_buffer,
|
||||||
const uchar* const record,
|
const uchar *const record, uchar *const packed_tuple,
|
||||||
uchar* const packed_tuple,
|
|
||||||
Rdb_string_writer *const unpack_info,
|
Rdb_string_writer *const unpack_info,
|
||||||
const bool &should_store_row_debug_checksums,
|
const bool &should_store_row_debug_checksums,
|
||||||
const longlong &hidden_pk_id = 0, uint n_key_parts = 0,
|
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,
|
int unpack_record(TABLE *const table, uchar *const buf,
|
||||||
const rocksdb::Slice *const packed_key,
|
const rocksdb::Slice *const packed_key,
|
||||||
const rocksdb::Slice *const unpack_info,
|
const rocksdb::Slice *const unpack_info,
|
||||||
const bool &verify_row_debug_checksums)
|
const bool &verify_row_debug_checksums) const;
|
||||||
const;
|
|
||||||
|
|
||||||
static bool unpack_info_has_checksum(const rocksdb::Slice &unpack_info);
|
static bool unpack_info_has_checksum(const rocksdb::Slice &unpack_info);
|
||||||
int compare_keys(const rocksdb::Slice *key1, const rocksdb::Slice *key2,
|
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;
|
size_t key_length(const TABLE *const table, const rocksdb::Slice &key) const;
|
||||||
|
|
||||||
/* Get the key that is the "infimum" for this index */
|
/* 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);
|
rdb_netbuf_store_index(key, m_index_number);
|
||||||
*size = INDEX_NUMBER_SIZE;
|
*size = INDEX_NUMBER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the key that is a "supremum" for this index */
|
/* 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);
|
rdb_netbuf_store_index(key, m_index_number + 1);
|
||||||
*size = INDEX_NUMBER_SIZE;
|
*size = INDEX_NUMBER_SIZE;
|
||||||
}
|
}
|
||||||
@@ -217,8 +208,7 @@ public:
|
|||||||
if X is a prefix of Y, then we consider that X = Y.
|
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.
|
// 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(a));
|
||||||
DBUG_ASSERT(covers_key(b));
|
DBUG_ASSERT(covers_key(b));
|
||||||
|
|
||||||
@@ -226,8 +216,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if given mem-comparable key belongs to this index */
|
/* 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)
|
if (slice.size() < INDEX_NUMBER_SIZE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -244,43 +233,35 @@ public:
|
|||||||
form)
|
form)
|
||||||
*/
|
*/
|
||||||
bool value_matches_prefix(const rocksdb::Slice &value,
|
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);
|
return covers_key(value) && !cmp_full_keys(value, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 get_keyno() const
|
uint32 get_keyno() const { return m_keyno; }
|
||||||
{
|
|
||||||
return m_keyno;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 get_index_number() const
|
uint32 get_index_number() const { return m_index_number; }
|
||||||
{
|
|
||||||
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};
|
const GL_INDEX_ID gl_index_id = {m_cf_handle->GetID(), m_index_number};
|
||||||
return gl_index_id;
|
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: */
|
/* Must only be called for secondary keys: */
|
||||||
uint get_primary_key_tuple(const TABLE *const tbl,
|
uint get_primary_key_tuple(const TABLE *const tbl,
|
||||||
const Rdb_key_def &pk_descr,
|
const Rdb_key_def &pk_descr,
|
||||||
const rocksdb::Slice *const key,
|
const rocksdb::Slice *const key,
|
||||||
uchar *const pk_buffer) const;
|
uchar *const pk_buffer) const;
|
||||||
|
|
||||||
/* Return max length of mem-comparable form */
|
uint get_memcmp_sk_parts(const TABLE *table, const rocksdb::Slice &key,
|
||||||
uint max_storage_fmt_length() const
|
uchar *sk_buffer, uint *n_null_fields) const;
|
||||||
{
|
|
||||||
return m_maxlength;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint get_key_parts() const
|
/* Return max length of mem-comparable form */
|
||||||
{
|
uint max_storage_fmt_length() const { return m_maxlength; }
|
||||||
return m_key_parts;
|
|
||||||
}
|
uint get_key_parts() const { return m_key_parts; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a field object for key part #part_no
|
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;
|
inline Field *get_table_field_for_part_no(TABLE *table, uint part_no) const;
|
||||||
|
|
||||||
const std::string& get_name() const {
|
const std::string &get_name() const { return m_name; }
|
||||||
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 &operator=(const Rdb_key_def &) = delete;
|
||||||
Rdb_key_def(const Rdb_key_def &k);
|
Rdb_key_def(const Rdb_key_def &k);
|
||||||
Rdb_key_def(uint indexnr_arg, uint keyno_arg,
|
Rdb_key_def(uint indexnr_arg, uint keyno_arg,
|
||||||
rocksdb::ColumnFamilyHandle *cf_handle_arg,
|
rocksdb::ColumnFamilyHandle *cf_handle_arg,
|
||||||
uint16_t index_dict_version_arg,
|
uint16_t index_dict_version_arg, uchar index_type_arg,
|
||||||
uchar index_type_arg,
|
uint16_t kv_format_version_arg, bool is_reverse_cf_arg,
|
||||||
uint16_t kv_format_version_arg,
|
bool is_auto_cf_arg, const char *name,
|
||||||
bool is_reverse_cf_arg, bool is_auto_cf_arg,
|
|
||||||
const char* name,
|
|
||||||
Rdb_index_stats stats = Rdb_index_stats());
|
Rdb_index_stats stats = Rdb_index_stats());
|
||||||
~Rdb_key_def();
|
~Rdb_key_def();
|
||||||
|
|
||||||
@@ -410,10 +391,8 @@ public:
|
|||||||
bool index_format_min_check(const int &pk_min, const int &sk_min) const;
|
bool index_format_min_check(const int &pk_min, const int &sk_min) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#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());
|
const int storage_length = static_cast<int>(max_storage_fmt_length());
|
||||||
return (storage_length - offset) >= needed;
|
return (storage_length - offset) >= needed;
|
||||||
}
|
}
|
||||||
@@ -437,8 +416,8 @@ public:
|
|||||||
bool m_is_auto_cf;
|
bool m_is_auto_cf;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
mutable Rdb_index_stats m_stats;
|
mutable Rdb_index_stats m_stats;
|
||||||
private:
|
|
||||||
|
|
||||||
|
private:
|
||||||
friend class Rdb_tbl_def; // for m_index_number above
|
friend class Rdb_tbl_def; // for m_index_number above
|
||||||
|
|
||||||
/* Number of key parts in the primary key*/
|
/* Number of key parts in the primary key*/
|
||||||
@@ -461,6 +440,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
uint m_key_parts;
|
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. */
|
/* Maximum length of the mem-comparable form. */
|
||||||
uint m_maxlength;
|
uint m_maxlength;
|
||||||
|
|
||||||
@@ -485,8 +467,7 @@ private:
|
|||||||
//
|
//
|
||||||
// We have m_dec_idx[idx][dst] = src to get our original character back.
|
// 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;
|
const my_core::CHARSET_INFO *m_cs;
|
||||||
// The first element unpacks VARCHAR(n), the second one - CHAR(n).
|
// The first element unpacks VARCHAR(n), the second one - CHAR(n).
|
||||||
std::array<rdb_make_unpack_info_t, 2> m_make_unpack_info_func;
|
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>
|
extern std::array<const Rdb_collation_codec *, MY_ALL_CHARSETS_SIZE>
|
||||||
rdb_collation_data;
|
rdb_collation_data;
|
||||||
|
|
||||||
|
class Rdb_field_packing {
|
||||||
class Rdb_field_packing
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_field_packing(const Rdb_field_packing &) = delete;
|
Rdb_field_packing(const Rdb_field_packing &) = delete;
|
||||||
Rdb_field_packing &operator=(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.
|
@return TRUE: this field makes use of unpack_info.
|
||||||
*/
|
*/
|
||||||
bool uses_unpack_info() const
|
bool uses_unpack_info() const { return (m_make_unpack_info_func != nullptr); }
|
||||||
{
|
|
||||||
return (m_make_unpack_info_func != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TRUE means unpack_info stores the original field value */
|
/* TRUE means unpack_info stores the original field value */
|
||||||
bool m_unpack_info_stores_value;
|
bool m_unpack_info_stores_value;
|
||||||
@@ -591,6 +567,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
uint m_keynr;
|
uint m_keynr;
|
||||||
uint m_key_part;
|
uint m_key_part;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool setup(const Rdb_key_def *const key_descr, const Field *const field,
|
bool setup(const Rdb_key_def *const key_descr, const Field *const field,
|
||||||
const uint &keynr_arg, const uint &key_part_arg,
|
const uint &keynr_arg, const uint &key_part_arg,
|
||||||
@@ -606,8 +583,7 @@ public:
|
|||||||
|
|
||||||
For encoding/decoding of index tuples, see Rdb_key_def.
|
For encoding/decoding of index tuples, see Rdb_key_def.
|
||||||
*/
|
*/
|
||||||
class Rdb_field_encoder
|
class Rdb_field_encoder {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_field_encoder(const Rdb_field_encoder &) = delete;
|
Rdb_field_encoder(const Rdb_field_encoder &) = delete;
|
||||||
Rdb_field_encoder &operator=(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 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 ||
|
return (m_field_type == MYSQL_TYPE_BLOB ||
|
||||||
m_field_type == MYSQL_TYPE_VARCHAR);
|
m_field_type == MYSQL_TYPE_VARCHAR);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Field *Rdb_key_def::get_table_field_for_part_no(TABLE *table,
|
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());
|
DBUG_ASSERT(part_no < get_key_parts());
|
||||||
return m_pack_info[part_no].get_field_in_table(table);
|
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);
|
DBUG_ASSERT(kp < m_key_parts);
|
||||||
return (m_pack_info[kp].m_unpack_func != nullptr);
|
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);
|
DBUG_ASSERT(kp < m_key_parts);
|
||||||
return m_pack_info[kp].uses_unpack_info();
|
return m_pack_info[kp].uses_unpack_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A table definition. This is an entry in the mapping
|
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.
|
That's why we keep auto_increment value here, too.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Rdb_tbl_def
|
class Rdb_tbl_def {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
void check_if_is_mysql_system_table();
|
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(const Rdb_tbl_def &) = delete;
|
||||||
Rdb_tbl_def &operator=(const Rdb_tbl_def &) = delete;
|
Rdb_tbl_def &operator=(const Rdb_tbl_def &) = delete;
|
||||||
|
|
||||||
explicit Rdb_tbl_def(const std::string& name) :
|
explicit Rdb_tbl_def(const std::string &name)
|
||||||
m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1)
|
: m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1) {
|
||||||
{
|
|
||||||
set_name(name);
|
set_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rdb_tbl_def(const char* const name, const size_t &len) :
|
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)
|
: m_key_descr_arr(nullptr), m_hidden_pk_val(1), m_auto_incr_val(1) {
|
||||||
{
|
|
||||||
set_name(std::string(name, len));
|
set_name(std::string(name, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Rdb_tbl_def(const rocksdb::Slice& slice, const size_t &pos= 0) :
|
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)
|
: 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));
|
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; }
|
const std::string &base_partition() const { return m_partition; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A thread-safe sequential number generator. Its performance is not a concern
|
A thread-safe sequential number generator. Its performance is not a concern
|
||||||
hence it is ok to protect it by a mutex.
|
hence it is ok to protect it by a mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Rdb_seq_generator
|
class Rdb_seq_generator {
|
||||||
{
|
|
||||||
uint m_next_number = 0;
|
uint m_next_number = 0;
|
||||||
|
|
||||||
mysql_mutex_t m_mutex;
|
mysql_mutex_t m_mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_seq_generator(const Rdb_seq_generator &) = delete;
|
Rdb_seq_generator(const Rdb_seq_generator &) = delete;
|
||||||
Rdb_seq_generator &operator=(const Rdb_seq_generator &) = delete;
|
Rdb_seq_generator &operator=(const Rdb_seq_generator &) = delete;
|
||||||
Rdb_seq_generator() = default;
|
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);
|
mysql_mutex_init(0, &m_mutex, MY_MUTEX_INIT_FAST);
|
||||||
m_next_number = initial_number;
|
m_next_number = initial_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint get_and_update_next_number(Rdb_dict_manager *const dict);
|
uint get_and_update_next_number(Rdb_dict_manager *const dict);
|
||||||
|
|
||||||
void cleanup()
|
void cleanup() { mysql_mutex_destroy(&m_mutex); }
|
||||||
{
|
|
||||||
mysql_mutex_destroy(&m_mutex);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface Rdb_tables_scanner {
|
||||||
interface Rdb_tables_scanner
|
|
||||||
{
|
|
||||||
virtual int add_table(Rdb_tbl_def * tdef) = 0;
|
virtual int add_table(Rdb_tbl_def * tdef) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This contains a mapping of
|
This contains a mapping of
|
||||||
|
|
||||||
@@ -778,8 +737,7 @@ interface Rdb_tables_scanner
|
|||||||
objects are shared among all threads.
|
objects are shared among all threads.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Rdb_ddl_manager
|
class Rdb_ddl_manager {
|
||||||
{
|
|
||||||
Rdb_dict_manager *m_dict = nullptr;
|
Rdb_dict_manager *m_dict = nullptr;
|
||||||
my_core::HASH m_ddl_hash; // Contains Rdb_tbl_def elements
|
my_core::HASH m_ddl_hash; // Contains Rdb_tbl_def elements
|
||||||
// maps index id to <table_name, index number>
|
// maps index id to <table_name, index number>
|
||||||
@@ -792,8 +750,8 @@ class Rdb_ddl_manager
|
|||||||
// and consumed by the rocksdb background thread
|
// and consumed by the rocksdb background thread
|
||||||
std::map<GL_INDEX_ID, Rdb_index_stats> m_stats2store;
|
std::map<GL_INDEX_ID, Rdb_index_stats> m_stats2store;
|
||||||
|
|
||||||
const std::shared_ptr<Rdb_key_def>& find(
|
const std::shared_ptr<Rdb_key_def> &find(GL_INDEX_ID gl_index_id);
|
||||||
GL_INDEX_ID gl_index_id);
|
|
||||||
public:
|
public:
|
||||||
Rdb_ddl_manager(const Rdb_ddl_manager &) = delete;
|
Rdb_ddl_manager(const Rdb_ddl_manager &) = delete;
|
||||||
Rdb_ddl_manager &operator=(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);
|
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);
|
std::shared_ptr<const Rdb_key_def> safe_find(GL_INDEX_ID gl_index_id);
|
||||||
void set_stats(
|
void set_stats(const std::unordered_map<GL_INDEX_ID, Rdb_index_stats> &stats);
|
||||||
const std::unordered_map<GL_INDEX_ID, Rdb_index_stats>& stats);
|
void adjust_stats(const std::vector<Rdb_index_stats> &new_data,
|
||||||
void adjust_stats(
|
const std::vector<Rdb_index_stats> &deleted_data =
|
||||||
const std::vector<Rdb_index_stats>& new_data,
|
std::vector<Rdb_index_stats>());
|
||||||
const std::vector<Rdb_index_stats>& deleted_data
|
|
||||||
=std::vector<Rdb_index_stats>());
|
|
||||||
void persist_stats(const bool &sync = false);
|
void persist_stats(const bool &sync = false);
|
||||||
|
|
||||||
/* Modify the mapping and write it to on-disk storage */
|
/* 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,
|
bool rename(const std::string &from, const std::string &to,
|
||||||
rocksdb::WriteBatch *const batch);
|
rocksdb::WriteBatch *const batch);
|
||||||
|
|
||||||
uint get_and_update_next_number(Rdb_dict_manager* const dict)
|
uint get_and_update_next_number(Rdb_dict_manager *const dict) {
|
||||||
{ return m_sequence.get_and_update_next_number(dict); }
|
return m_sequence.get_and_update_next_number(dict);
|
||||||
|
}
|
||||||
|
|
||||||
/* Walk the data dictionary */
|
/* Walk the data dictionary */
|
||||||
int scan_for_tables(Rdb_tables_scanner *tables_scanner);
|
int scan_for_tables(Rdb_tables_scanner *tables_scanner);
|
||||||
@@ -837,13 +794,12 @@ private:
|
|||||||
|
|
||||||
/* Helper functions to be passed to my_core::HASH object */
|
/* 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,
|
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);
|
static void free_hash_elem(void *const data);
|
||||||
|
|
||||||
bool validate_schemas();
|
bool validate_schemas();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Writing binlog information into RocksDB at commit(),
|
Writing binlog information into RocksDB at commit(),
|
||||||
and retrieving binlog information at crash recovery.
|
and retrieving binlog information at crash recovery.
|
||||||
@@ -859,8 +815,7 @@ private:
|
|||||||
binlog_gtid_length (2 byte form)
|
binlog_gtid_length (2 byte form)
|
||||||
binlog_gtid
|
binlog_gtid
|
||||||
*/
|
*/
|
||||||
class Rdb_binlog_manager
|
class Rdb_binlog_manager {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Rdb_binlog_manager(const Rdb_binlog_manager &) = delete;
|
Rdb_binlog_manager(const Rdb_binlog_manager &) = delete;
|
||||||
Rdb_binlog_manager &operator=(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};
|
uchar m_key_buf[Rdb_key_def::INDEX_NUMBER_SIZE] = {0};
|
||||||
rocksdb::Slice m_key_slice;
|
rocksdb::Slice m_key_slice;
|
||||||
|
|
||||||
rocksdb::Slice pack_value(uchar* const buf,
|
rocksdb::Slice pack_value(uchar *const buf, const char *const binlog_name,
|
||||||
const char* const binlog_name,
|
|
||||||
const my_off_t &binlog_pos,
|
const my_off_t &binlog_pos,
|
||||||
const char *const binlog_gtid) const;
|
const char *const binlog_gtid) const;
|
||||||
bool unpack_value(const uchar *const value, char *const binlog_name,
|
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;
|
std::atomic<Rdb_tbl_def *> m_slave_gtid_info_tbl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Rdb_dict_manager manages how MySQL on RocksDB (MyRocks) stores its
|
Rdb_dict_manager manages how MySQL on RocksDB (MyRocks) stores its
|
||||||
internal data dictionary.
|
internal data dictionary.
|
||||||
@@ -944,8 +897,7 @@ private:
|
|||||||
begin() and commit() to make it easier to do atomic operations.
|
begin() and commit() to make it easier to do atomic operations.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
class Rdb_dict_manager
|
class Rdb_dict_manager {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
mysql_mutex_t m_mutex;
|
mysql_mutex_t m_mutex;
|
||||||
rocksdb::DB *m_db = nullptr;
|
rocksdb::DB *m_db = nullptr;
|
||||||
@@ -968,6 +920,7 @@ private:
|
|||||||
const char *const log_action) const;
|
const char *const log_action) const;
|
||||||
void log_start_drop_index(GL_INDEX_ID gl_index_id,
|
void log_start_drop_index(GL_INDEX_ID gl_index_id,
|
||||||
const char *log_action) const;
|
const char *log_action) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_dict_manager(const Rdb_dict_manager &) = delete;
|
Rdb_dict_manager(const Rdb_dict_manager &) = delete;
|
||||||
Rdb_dict_manager &operator=(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);
|
bool init(rocksdb::DB *const rdb_dict, Rdb_cf_manager *const cf_manager);
|
||||||
|
|
||||||
inline void cleanup()
|
inline void cleanup() { mysql_mutex_destroy(&m_mutex); }
|
||||||
{
|
|
||||||
mysql_mutex_destroy(&m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void lock()
|
inline void lock() { mysql_mutex_lock(&m_mutex); }
|
||||||
{
|
|
||||||
mysql_mutex_lock(&m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void unlock()
|
inline void unlock() { mysql_mutex_unlock(&m_mutex); }
|
||||||
{
|
|
||||||
mysql_mutex_unlock(&m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Raw RocksDB operations */
|
/* Raw RocksDB operations */
|
||||||
std::unique_ptr<rocksdb::WriteBatch> begin() const;
|
std::unique_ptr<rocksdb::WriteBatch> begin() const;
|
||||||
@@ -1010,17 +954,17 @@ public:
|
|||||||
void delete_index_info(rocksdb::WriteBatch *batch,
|
void delete_index_info(rocksdb::WriteBatch *batch,
|
||||||
const GL_INDEX_ID &index_id) const;
|
const GL_INDEX_ID &index_id) const;
|
||||||
bool get_index_info(const GL_INDEX_ID &gl_index_id,
|
bool get_index_info(const GL_INDEX_ID &gl_index_id,
|
||||||
uint16_t *index_dict_version,
|
uint16_t *index_dict_version, uchar *index_type,
|
||||||
uchar *index_type, uint16_t *kv_version) const;
|
uint16_t *kv_version) const;
|
||||||
|
|
||||||
/* CF id => CF flags */
|
/* CF id => CF flags */
|
||||||
void add_cf_flags(rocksdb::WriteBatch* const batch,
|
void add_cf_flags(rocksdb::WriteBatch *const batch, const uint &cf_id,
|
||||||
const uint &cf_id,
|
|
||||||
const uint &cf_flags) const;
|
const uint &cf_flags) const;
|
||||||
bool get_cf_flags(const uint &cf_id, uint *const cf_flags) const;
|
bool get_cf_flags(const uint &cf_id, uint *const cf_flags) const;
|
||||||
|
|
||||||
/* Functions for fast CREATE/DROP TABLE/INDEX */
|
/* 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;
|
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
|
||||||
bool is_index_operation_ongoing(const GL_INDEX_ID &gl_index_id,
|
bool is_index_operation_ongoing(const GL_INDEX_ID &gl_index_id,
|
||||||
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
|
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
|
||||||
@@ -1038,54 +982,45 @@ public:
|
|||||||
rocksdb::WriteBatch *const batch) const;
|
rocksdb::WriteBatch *const batch) const;
|
||||||
void add_create_index(const std::unordered_set<GL_INDEX_ID> &gl_index_ids,
|
void add_create_index(const std::unordered_set<GL_INDEX_ID> &gl_index_ids,
|
||||||
rocksdb::WriteBatch *const batch) const;
|
rocksdb::WriteBatch *const batch) const;
|
||||||
void finish_indexes_operation(
|
void
|
||||||
const std::unordered_set<GL_INDEX_ID>& gl_index_ids,
|
finish_indexes_operation(const std::unordered_set<GL_INDEX_ID> &gl_index_ids,
|
||||||
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
|
Rdb_key_def::DATA_DICT_TYPE dd_type) const;
|
||||||
void rollback_ongoing_index_creation() const;
|
void rollback_ongoing_index_creation() const;
|
||||||
|
|
||||||
inline void
|
inline void get_ongoing_drop_indexes(
|
||||||
get_ongoing_drop_indexes(std::vector<GL_INDEX_ID>* gl_index_ids) const
|
std::unordered_set<GL_INDEX_ID> *gl_index_ids) const {
|
||||||
{
|
|
||||||
get_ongoing_index_operation(gl_index_ids,
|
get_ongoing_index_operation(gl_index_ids,
|
||||||
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
|
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
|
||||||
}
|
}
|
||||||
inline void
|
inline void get_ongoing_create_indexes(
|
||||||
get_ongoing_create_indexes(std::vector<GL_INDEX_ID>* gl_index_ids) const
|
std::unordered_set<GL_INDEX_ID> *gl_index_ids) const {
|
||||||
{
|
|
||||||
get_ongoing_index_operation(gl_index_ids,
|
get_ongoing_index_operation(gl_index_ids,
|
||||||
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
||||||
}
|
}
|
||||||
inline void start_drop_index(rocksdb::WriteBatch *wb,
|
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,
|
start_ongoing_index_operation(wb, gl_index_id,
|
||||||
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
|
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
|
||||||
}
|
}
|
||||||
inline void start_create_index(rocksdb::WriteBatch *wb,
|
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,
|
start_ongoing_index_operation(wb, gl_index_id,
|
||||||
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
||||||
}
|
}
|
||||||
inline void finish_drop_indexes(
|
inline void finish_drop_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_DROP_INDEX_ONGOING);
|
||||||
finish_indexes_operation(gl_index_ids,
|
|
||||||
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
|
|
||||||
}
|
}
|
||||||
inline void finish_create_indexes(
|
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,
|
finish_indexes_operation(gl_index_ids,
|
||||||
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
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,
|
return is_index_operation_ongoing(gl_index_id,
|
||||||
Rdb_key_def::DDL_DROP_INDEX_ONGOING);
|
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,
|
return is_index_operation_ongoing(gl_index_id,
|
||||||
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
Rdb_key_def::DDL_CREATE_INDEX_ONGOING);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||||
extern struct st_mysql_plugin rdb_i_s_perf_context_global;
|
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_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_global_info;
|
||||||
extern struct st_mysql_plugin rdb_i_s_ddl;
|
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_index_file_map;
|
||||||
extern struct st_mysql_plugin rdb_i_s_lock_info;
|
extern struct st_mysql_plugin rdb_i_s_lock_info;
|
||||||
extern struct st_mysql_plugin rdb_i_s_trx_info;
|
extern struct st_mysql_plugin rdb_i_s_trx_info;
|
||||||
} // namespace myrocks
|
} // namespace myrocks
|
||||||
|
|
||||||
|
@@ -17,6 +17,9 @@
|
|||||||
/* This C++ file's header file */
|
/* This C++ file's header file */
|
||||||
#include "./rdb_index_merge.h"
|
#include "./rdb_index_merge.h"
|
||||||
|
|
||||||
|
/* MySQL header files */
|
||||||
|
#include "../sql/sql_class.h"
|
||||||
|
|
||||||
/* MyRocks header files */
|
/* MyRocks header files */
|
||||||
#include "./ha_rocksdb.h"
|
#include "./ha_rocksdb.h"
|
||||||
#include "./rdb_datadic.h"
|
#include "./rdb_datadic.h"
|
||||||
@@ -26,38 +29,25 @@ namespace myrocks {
|
|||||||
Rdb_index_merge::Rdb_index_merge(const char *const tmpfile_path,
|
Rdb_index_merge::Rdb_index_merge(const char *const tmpfile_path,
|
||||||
const ulonglong &merge_buf_size,
|
const ulonglong &merge_buf_size,
|
||||||
const ulonglong &merge_combine_read_size,
|
const ulonglong &merge_combine_read_size,
|
||||||
const rocksdb::Comparator* const comparator) :
|
const rocksdb::Comparator *const comparator)
|
||||||
m_tmpfile_path(tmpfile_path),
|
: m_tmpfile_path(tmpfile_path), m_merge_buf_size(merge_buf_size),
|
||||||
m_merge_buf_size(merge_buf_size),
|
|
||||||
m_merge_combine_read_size(merge_combine_read_size),
|
m_merge_combine_read_size(merge_combine_read_size),
|
||||||
m_comparator(comparator),
|
m_comparator(comparator), m_rec_buf_unsorted(nullptr),
|
||||||
m_rec_buf_unsorted(nullptr),
|
m_output_buf(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.
|
Close tmp file, we don't need to worry about deletion, mysql handles it.
|
||||||
*/
|
*/
|
||||||
my_close(m_merge_file.fd, MYF(MY_WME));
|
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
|
Create a temporary merge file on disk to store sorted chunks during
|
||||||
inplace index creation.
|
inplace index creation.
|
||||||
*/
|
*/
|
||||||
if (merge_file_create())
|
if (merge_file_create()) {
|
||||||
{
|
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
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
|
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.
|
keep track of the offset of each record within the unsorted buffer.
|
||||||
*/
|
*/
|
||||||
m_rec_buf_unsorted= std::shared_ptr<merge_buf_info>(
|
m_rec_buf_unsorted =
|
||||||
new merge_buf_info(m_merge_buf_size));
|
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
|
Allocate output buffer that will contain sorted block that is written to
|
||||||
disk.
|
disk.
|
||||||
*/
|
*/
|
||||||
m_output_buf= std::shared_ptr<merge_buf_info>(
|
m_output_buf =
|
||||||
new merge_buf_info(m_merge_buf_size));
|
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.
|
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);
|
DBUG_ASSERT(m_merge_file.fd == -1);
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
/* If no path set for tmpfile, use mysql_tmpdir by default */
|
/* 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");
|
fd = mysql_tmpfile("myrocks");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fd = mysql_tmpfile_path(m_tmpfile_path, "myrocks");
|
fd = mysql_tmpfile_path(m_tmpfile_path, "myrocks");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0) {
|
||||||
{
|
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_merge_file.fd = fd;
|
m_merge_file.fd = fd;
|
||||||
m_merge_file.num_sort_buffers = 0;
|
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
|
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)
|
offset tree, and clear the tree. (Happens in merge_buf_write)
|
||||||
*/
|
*/
|
||||||
int Rdb_index_merge::add(const rocksdb::Slice& key,
|
int Rdb_index_merge::add(const rocksdb::Slice &key, const rocksdb::Slice &val) {
|
||||||
const rocksdb::Slice& val)
|
|
||||||
{
|
|
||||||
/* Adding a record after heap is already created results in error */
|
/* Adding a record after heap is already created results in error */
|
||||||
DBUG_ASSERT(m_merge_min_heap.empty());
|
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
|
Check if sort buffer is going to be out of space, if so write it
|
||||||
out to disk in sorted order using offset tree.
|
out to disk in sorted order using offset tree.
|
||||||
*/
|
*/
|
||||||
const uint total_offset=
|
const uint total_offset = RDB_MERGE_CHUNK_LEN +
|
||||||
RDB_MERGE_CHUNK_LEN + m_rec_buf_unsorted->curr_offset +
|
m_rec_buf_unsorted->curr_offset +
|
||||||
RDB_MERGE_KEY_DELIMITER + RDB_MERGE_VAL_DELIMITER +
|
RDB_MERGE_KEY_DELIMITER + RDB_MERGE_VAL_DELIMITER +
|
||||||
key.size() + val.size();
|
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
|
If the offset tree is empty here, that means that the proposed key to
|
||||||
add is too large for the buffer.
|
add is too large for the buffer.
|
||||||
*/
|
*/
|
||||||
if (m_offset_tree.empty())
|
if (m_offset_tree.empty()) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Sort buffer size is too small to process merge. "
|
sql_print_error("Sort buffer size is too small to process merge. "
|
||||||
"Please set merge buffer size to a higher value.");
|
"Please set merge buffer size to a higher value.");
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (merge_buf_write())
|
if (merge_buf_write()) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error writing sort buffer to disk.");
|
sql_print_error("Error writing sort buffer to disk.");
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
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_offset_tree.emplace(m_rec_buf_unsorted->block.get() + rec_offset,
|
||||||
m_comparator);
|
m_comparator);
|
||||||
|
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sort + write merge buffer chunk out to disk.
|
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_merge_file.fd != -1);
|
||||||
DBUG_ASSERT(m_rec_buf_unsorted != nullptr);
|
DBUG_ASSERT(m_rec_buf_unsorted != nullptr);
|
||||||
DBUG_ASSERT(m_output_buf != 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
|
Iterate through the offset tree. Should be ordered by the secondary key
|
||||||
at this point.
|
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);
|
DBUG_ASSERT(m_output_buf->curr_offset <= m_merge_buf_size);
|
||||||
|
|
||||||
/* Read record from offset (should never fail) */
|
/* 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.
|
then write into the respective merge buffer.
|
||||||
*/
|
*/
|
||||||
if (my_seek(m_merge_file.fd, m_merge_file.num_sort_buffers * m_merge_buf_size,
|
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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error seeking to location in merge file on disk.");
|
sql_print_error("Error seeking to location in merge file on disk.");
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
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(),
|
if (my_write(m_merge_file.fd, m_output_buf->block.get(),
|
||||||
m_output_buf->total_size, MYF(MY_WME | MY_NABP)) ||
|
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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error writing sorted merge buffer to disk.");
|
sql_print_error("Error writing sorted merge buffer to disk.");
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
@@ -234,23 +210,21 @@ int Rdb_index_merge::merge_buf_write()
|
|||||||
/* Reset everything for next run */
|
/* Reset everything for next run */
|
||||||
merge_reset();
|
merge_reset();
|
||||||
|
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Prepare n-way merge of n sorted buffers on disk, using a heap sorted by
|
Prepare n-way merge of n sorted buffers on disk, using a heap sorted by
|
||||||
secondary key records.
|
secondary key records.
|
||||||
*/
|
*/
|
||||||
int Rdb_index_merge::merge_heap_prepare()
|
int Rdb_index_merge::merge_heap_prepare() {
|
||||||
{
|
|
||||||
DBUG_ASSERT(m_merge_min_heap.empty());
|
DBUG_ASSERT(m_merge_min_heap.empty());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If the offset tree is not empty, there are still some records that need to
|
If the offset tree is not empty, there are still some records that need to
|
||||||
be written to disk. Write them out now.
|
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;
|
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
|
For an n-way merge, we need to read chunks of each merge file
|
||||||
simultaneously.
|
simultaneously.
|
||||||
*/
|
*/
|
||||||
ulonglong chunk_size= m_merge_combine_read_size/
|
ulonglong chunk_size =
|
||||||
m_merge_file.num_sort_buffers;
|
m_merge_combine_read_size / m_merge_file.num_sort_buffers;
|
||||||
if (chunk_size >= m_merge_buf_size)
|
if (chunk_size >= m_merge_buf_size) {
|
||||||
{
|
|
||||||
chunk_size = m_merge_buf_size;
|
chunk_size = m_merge_buf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate buffers for each chunk */
|
/* 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);
|
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 =
|
const size_t total_size =
|
||||||
entry->prepare(m_merge_file.fd, i * m_merge_buf_size, chunk_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;
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can reach this condition if an index was added on table w/ no rows */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the first record from each buffer to initially populate the heap */
|
/* 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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Chunk size is too small to process merge.");
|
sql_print_error("Chunk size is too small to process merge.");
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
@@ -301,14 +270,14 @@ int Rdb_index_merge::merge_heap_prepare()
|
|||||||
m_merge_min_heap.push(std::move(entry));
|
m_merge_min_heap.push(std::move(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create and/or iterate through keys in the merge heap.
|
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
|
If table fits in one sort buffer, we can optimize by writing
|
||||||
the sort buffer directly through to the sstfilewriter instead of
|
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),
|
If there are no sort buffer records (alters on empty tables),
|
||||||
also exit here.
|
also exit here.
|
||||||
*/
|
*/
|
||||||
if (m_merge_file.num_sort_buffers == 0)
|
if (m_merge_file.num_sort_buffers == 0) {
|
||||||
{
|
if (m_offset_tree.empty()) {
|
||||||
if (m_offset_tree.empty())
|
|
||||||
{
|
|
||||||
return -1;
|
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);
|
merge_read_rec(rec->block, key, val);
|
||||||
|
|
||||||
m_offset_tree.erase(rec);
|
m_offset_tree.erase(rec);
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res;
|
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
|
of the external sort. Populate the heap with initial values from each
|
||||||
disk chunk.
|
disk chunk.
|
||||||
*/
|
*/
|
||||||
if (m_merge_min_heap.empty())
|
if (m_merge_min_heap.empty()) {
|
||||||
{
|
if ((res = merge_heap_prepare())) {
|
||||||
if ((res= merge_heap_prepare()))
|
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error during preparation of heap.");
|
sql_print_error("Error during preparation of heap.");
|
||||||
return res;
|
return res;
|
||||||
@@ -354,7 +319,7 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
|||||||
inside the SST file yet.
|
inside the SST file yet.
|
||||||
*/
|
*/
|
||||||
merge_heap_top(key, val);
|
merge_heap_top(key, val);
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_ASSERT(!m_merge_min_heap.empty());
|
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.
|
Get current top record from the heap.
|
||||||
*/
|
*/
|
||||||
void Rdb_index_merge::merge_heap_top(rocksdb::Slice *const key,
|
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());
|
DBUG_ASSERT(!m_merge_min_heap.empty());
|
||||||
|
|
||||||
const std::shared_ptr<merge_heap_entry> &entry = m_merge_min_heap.top();
|
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.
|
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,
|
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
|
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.
|
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.
|
Return without adding entry back onto heap.
|
||||||
If heap is also empty, we must be finished with merge.
|
If heap is also empty, we must be finished with merge.
|
||||||
*/
|
*/
|
||||||
if (entry->chunk_info->is_chunk_finished())
|
if (entry->chunk_info->is_chunk_finished()) {
|
||||||
{
|
if (m_merge_min_heap.empty()) {
|
||||||
if (m_merge_min_heap.empty())
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
merge_heap_top(key, val);
|
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
|
If merge_read_rec fails, it means the either the chunk was cut off
|
||||||
or we've reached the end of the respective chunk.
|
or we've reached the end of the respective chunk.
|
||||||
*/
|
*/
|
||||||
if (entry->read_rec(&entry->key, &entry->val))
|
if (entry->read_rec(&entry->key, &entry->val)) {
|
||||||
{
|
if (entry->read_next_chunk_from_disk(m_merge_file.fd)) {
|
||||||
if (entry->read_next_chunk_from_disk(m_merge_file.fd))
|
|
||||||
{
|
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try reading record again, should never fail. */
|
/* 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;
|
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 */
|
/* Return the current top record on heap */
|
||||||
merge_heap_top(key, val);
|
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)
|
int Rdb_index_merge::merge_heap_entry::read_next_chunk_from_disk(File fd) {
|
||||||
{
|
if (chunk_info->read_next_chunk_from_disk(fd)) {
|
||||||
if (chunk_info->read_next_chunk_from_disk(fd))
|
return HA_EXIT_FAILURE;
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
block = chunk_info->block.get();
|
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;
|
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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error seeking to location in merge file on disk.");
|
sql_print_error("Error seeking to location in merge file on disk.");
|
||||||
return 1;
|
return HA_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overwrite the old block */
|
/* Overwrite the old block */
|
||||||
const size_t bytes_read = my_read(fd, block.get(), block_len, MYF(MY_WME));
|
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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error reading merge file from disk.");
|
sql_print_error("Error reading merge file from disk.");
|
||||||
return 1;
|
return HA_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
curr_offset = 0;
|
curr_offset = 0;
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get records from offset within sort buffer and compare them.
|
Get records from offset within sort buffer and compare them.
|
||||||
Sort by least to greatest.
|
Sort by least to greatest.
|
||||||
*/
|
*/
|
||||||
int Rdb_index_merge::merge_record_compare(const uchar* const a_block,
|
int Rdb_index_merge::merge_record_compare(
|
||||||
const uchar* const b_block,
|
const uchar *const a_block, const uchar *const b_block,
|
||||||
const rocksdb::Comparator* const comparator)
|
const rocksdb::Comparator *const comparator) {
|
||||||
{
|
|
||||||
return comparator->Compare(as_slice(a_block), as_slice(b_block));
|
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,
|
void Rdb_index_merge::merge_read_rec(const uchar *const block,
|
||||||
rocksdb::Slice *const key,
|
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 key at block offset into key slice and the value into value slice*/
|
||||||
read_slice(key, block);
|
read_slice(key, block);
|
||||||
read_slice(val, block + RDB_MERGE_REC_DELIMITER + key->size());
|
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;
|
uint64 slice_len;
|
||||||
merge_read_uint64(&block_ptr, &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,
|
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 uchar *block_ptr = block;
|
||||||
const auto orig_offset = chunk_info->curr_offset;
|
const auto orig_offset = chunk_info->curr_offset;
|
||||||
const auto orig_block = block;
|
const auto orig_block = block;
|
||||||
|
|
||||||
/* Read key at block offset into key slice and the value into value slice*/
|
/* Read key at block offset into key slice and the value into value slice*/
|
||||||
if (read_slice(key, &block_ptr) != 0)
|
if (read_slice(key, &block_ptr) != 0) {
|
||||||
{
|
return HA_EXIT_FAILURE;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
|
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
|
||||||
block += (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;
|
chunk_info->curr_offset = orig_offset;
|
||||||
block = orig_block;
|
block = orig_block;
|
||||||
return 1;
|
return HA_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
|
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
|
||||||
block += (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,
|
int Rdb_index_merge::merge_heap_entry::read_slice(rocksdb::Slice *const slice,
|
||||||
const uchar** block_ptr)
|
const uchar **block_ptr) {
|
||||||
{
|
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER)) {
|
||||||
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER))
|
return HA_EXIT_FAILURE;
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 slice_len;
|
uint64 slice_len;
|
||||||
merge_read_uint64(block_ptr, &slice_len);
|
merge_read_uint64(block_ptr, &slice_len);
|
||||||
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER + slice_len))
|
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER + slice_len)) {
|
||||||
{
|
return HA_EXIT_FAILURE;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*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;
|
*block_ptr += slice_len;
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Rdb_index_merge::merge_heap_entry::prepare(File fd, ulonglong f_offset,
|
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);
|
chunk_info = std::make_shared<merge_buf_info>(chunk_size);
|
||||||
const size_t res = chunk_info->prepare(fd, f_offset);
|
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;
|
block = chunk_info->block.get() + RDB_MERGE_CHUNK_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
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_start_offset = f_offset;
|
||||||
disk_curr_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
|
Need to position cursor to the chunk it needs to be at on filesystem
|
||||||
then read 'chunk_size' bytes into the respective chunk buffer.
|
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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error seeking to location in merge file on disk.");
|
sql_print_error("Error seeking to location in merge file on disk.");
|
||||||
return (size_t)-1;
|
return (size_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t bytes_read = my_read(fd, block.get(), total_size, MYF(MY_WME));
|
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
|
// NO_LINT_DEBUG
|
||||||
sql_print_error("Error reading merge file from disk.");
|
sql_print_error("Error reading merge file from disk.");
|
||||||
return (size_t)-1;
|
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 */
|
/* Store key and value w/ their respective delimiters at the given offset */
|
||||||
void Rdb_index_merge::merge_buf_info::store_key_value(
|
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(key);
|
||||||
store_slice(val);
|
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 */
|
/* Store length delimiter */
|
||||||
merge_store_uint64(&block[curr_offset], slice.size());
|
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;
|
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,
|
Either error, or all values in the sort buffer have been written to disk,
|
||||||
so we need to clear the offset tree.
|
so we need to clear the offset tree.
|
||||||
@@ -632,14 +569,12 @@ void Rdb_index_merge::merge_reset()
|
|||||||
m_offset_tree.clear();
|
m_offset_tree.clear();
|
||||||
|
|
||||||
/* Reset sort buffer block */
|
/* 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;
|
m_rec_buf_unsorted->curr_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset output buf */
|
/* 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;
|
m_output_buf->curr_offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,9 +22,9 @@
|
|||||||
#include "./my_global.h" /* ulonglong */
|
#include "./my_global.h" /* ulonglong */
|
||||||
|
|
||||||
/* C++ standard header files */
|
/* C++ standard header files */
|
||||||
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
/* RocksDB header files */
|
/* RocksDB header files */
|
||||||
#include "rocksdb/db.h"
|
#include "rocksdb/db.h"
|
||||||
@@ -60,38 +60,35 @@ class Rdb_index_merge {
|
|||||||
struct merge_buf_info {
|
struct merge_buf_info {
|
||||||
/* heap memory allocated for main memory sort/merge */
|
/* heap memory allocated for main memory sort/merge */
|
||||||
std::unique_ptr<uchar[]> block;
|
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 curr_offset; /* offset of the record pointer for the block */
|
||||||
ulonglong disk_start_offset; /* where the chunk starts on disk */
|
ulonglong disk_start_offset; /* where the chunk starts on disk */
|
||||||
ulonglong disk_curr_offset; /* current offset on disk */
|
ulonglong disk_curr_offset; /* current offset on disk */
|
||||||
ulonglong total_size; /* total # of data bytes in chunk */
|
ulonglong total_size; /* total # of data bytes in chunk */
|
||||||
|
|
||||||
void store_key_value(const rocksdb::Slice &key, const rocksdb::Slice &val)
|
void store_key_value(const rocksdb::Slice &key, const rocksdb::Slice &val)
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
void store_slice(const rocksdb::Slice& slice)
|
void store_slice(const rocksdb::Slice &slice) MY_ATTRIBUTE((__nonnull__));
|
||||||
__attribute__((__nonnull__));
|
|
||||||
|
|
||||||
size_t prepare(File fd, ulonglong f_offset)
|
size_t prepare(File fd, ulonglong f_offset) MY_ATTRIBUTE((__nonnull__));
|
||||||
__attribute__((__nonnull__));
|
|
||||||
|
|
||||||
int read_next_chunk_from_disk(File fd)
|
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;
|
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;
|
return curr_offset + needed <= block_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit merge_buf_info(const ulonglong merge_block_size) :
|
explicit merge_buf_info(const ulonglong merge_block_size)
|
||||||
block(nullptr), block_len(merge_block_size), curr_offset(0),
|
: block(nullptr), block_len(merge_block_size), curr_offset(0),
|
||||||
disk_start_offset(0), disk_curr_offset(0), total_size(merge_block_size)
|
disk_start_offset(0), disk_curr_offset(0),
|
||||||
{
|
total_size(merge_block_size) {
|
||||||
/* Will throw an exception if it runs out of memory here */
|
/* Will throw an exception if it runs out of memory here */
|
||||||
block = std::unique_ptr<uchar[]>(new uchar[merge_block_size]);
|
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 */
|
/* 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 */
|
std::shared_ptr<merge_buf_info> chunk_info; /* pointer to buffer info */
|
||||||
uchar *block; /* pointer to heap memory where record is stored */
|
uchar *block; /* pointer to heap memory where record is stored */
|
||||||
const rocksdb::Comparator *const comparator;
|
const rocksdb::Comparator *const comparator;
|
||||||
@@ -110,44 +106,40 @@ class Rdb_index_merge {
|
|||||||
rocksdb::Slice val;
|
rocksdb::Slice val;
|
||||||
|
|
||||||
size_t prepare(File fd, ulonglong f_offset, ulonglong chunk_size)
|
size_t prepare(File fd, ulonglong f_offset, ulonglong chunk_size)
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
int read_next_chunk_from_disk(File fd)
|
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)
|
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)
|
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) :
|
explicit merge_heap_entry(const rocksdb::Comparator *const comparator)
|
||||||
chunk_info(nullptr), block(nullptr), comparator(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,
|
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;
|
return lhs->comparator->Compare(rhs->key, lhs->key) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Represents a record in unsorted buffer */
|
/* Represents a record in unsorted buffer */
|
||||||
struct merge_record
|
struct merge_record {
|
||||||
{
|
|
||||||
uchar *block; /* points to offset of key in sort buffer */
|
uchar *block; /* points to offset of key in sort buffer */
|
||||||
const rocksdb::Comparator *const comparator;
|
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;
|
return merge_record_compare(this->block, record.block, comparator) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
merge_record(uchar *const block,
|
merge_record(uchar *const block,
|
||||||
const rocksdb::Comparator* const comparator) :
|
const rocksdb::Comparator *const comparator)
|
||||||
block(block), comparator(comparator) {}
|
: block(block), comparator(comparator) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -161,22 +153,21 @@ class Rdb_index_merge {
|
|||||||
std::set<merge_record> m_offset_tree;
|
std::set<merge_record> m_offset_tree;
|
||||||
std::priority_queue<std::shared_ptr<merge_heap_entry>,
|
std::priority_queue<std::shared_ptr<merge_heap_entry>,
|
||||||
std::vector<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));
|
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);
|
DBUG_ASSERT(buf_ptr != nullptr);
|
||||||
memcpy(dst, *buf_ptr, sizeof(uint64));
|
memcpy(dst, *buf_ptr, sizeof(uint64));
|
||||||
*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;
|
uint64 len;
|
||||||
merge_read_uint64(&block, &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,
|
static int merge_record_compare(const uchar *a_block, const uchar *b_block,
|
||||||
const rocksdb::Comparator *const comparator)
|
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,
|
void merge_read_rec(const uchar *const block, rocksdb::Slice *const key,
|
||||||
rocksdb::Slice* const val)
|
rocksdb::Slice *const val) MY_ATTRIBUTE((__nonnull__));
|
||||||
__attribute__((__nonnull__));
|
|
||||||
|
|
||||||
void read_slice(rocksdb::Slice *slice, const uchar *block_ptr)
|
void read_slice(rocksdb::Slice *slice, const uchar *block_ptr)
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_index_merge(const char *const tmpfile_path,
|
Rdb_index_merge(const char *const tmpfile_path,
|
||||||
@@ -201,30 +191,26 @@ class Rdb_index_merge {
|
|||||||
const rocksdb::Comparator *const comparator);
|
const rocksdb::Comparator *const comparator);
|
||||||
~Rdb_index_merge();
|
~Rdb_index_merge();
|
||||||
|
|
||||||
int init()
|
int init() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
|
||||||
|
|
||||||
int merge_file_create()
|
int merge_file_create() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
|
||||||
|
|
||||||
int add(const rocksdb::Slice &key, const rocksdb::Slice &val)
|
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()
|
int merge_buf_write() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
|
||||||
|
|
||||||
int next(rocksdb::Slice *const key, rocksdb::Slice *const val)
|
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()
|
int merge_heap_prepare() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
|
||||||
|
|
||||||
void merge_heap_top(rocksdb::Slice *key, rocksdb::Slice *val)
|
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,
|
int merge_heap_pop_and_get_next(rocksdb::Slice *const key,
|
||||||
rocksdb::Slice *const val)
|
rocksdb::Slice *const val)
|
||||||
__attribute__((__nonnull__, __warn_unused_result__));
|
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||||
|
|
||||||
void merge_reset();
|
void merge_reset();
|
||||||
};
|
};
|
||||||
|
@@ -17,43 +17,35 @@
|
|||||||
/* This C++ file's header file */
|
/* This C++ file's header file */
|
||||||
#include "./rdb_mutex_wrapper.h"
|
#include "./rdb_mutex_wrapper.h"
|
||||||
|
|
||||||
|
/* MySQL header files */
|
||||||
|
#include "../sql/sql_class.h"
|
||||||
|
#include "../sql/replication.h"
|
||||||
|
|
||||||
/* MyRocks header files */
|
/* MyRocks header files */
|
||||||
#include "./ha_rocksdb.h"
|
#include "./ha_rocksdb.h"
|
||||||
#include "./rdb_utils.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;
|
using namespace rocksdb;
|
||||||
|
|
||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
static
|
static PSI_stage_info stage_waiting_on_row_lock2 = {0, "Waiting for row lock",
|
||||||
PSI_stage_info stage_waiting_on_row_lock2= { 0, "Waiting for row lock", 0};
|
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
|
// A timeout as long as one full non-leap year worth of microseconds is as
|
||||||
// good as infinite timeout.
|
// 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() {
|
Rdb_cond_var::Rdb_cond_var() { mysql_cond_init(0, &m_cond, nullptr); }
|
||||||
mysql_cond_init(0, &m_cond, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rdb_cond_var::~Rdb_cond_var() {
|
Rdb_cond_var::~Rdb_cond_var() { mysql_cond_destroy(&m_cond); }
|
||||||
mysql_cond_destroy(&m_cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status Rdb_cond_var::Wait(const std::shared_ptr<TransactionDBMutex> mutex_arg) {
|
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
|
@brief
|
||||||
Wait on condition variable. The caller must make sure that we own
|
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
|
Status
|
||||||
Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
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());
|
auto *mutex_obj = reinterpret_cast<Rdb_mutex *>(mutex_arg.get());
|
||||||
DBUG_ASSERT(mutex_obj != nullptr);
|
DBUG_ASSERT(mutex_obj != nullptr);
|
||||||
|
|
||||||
@@ -81,21 +72,20 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
|||||||
struct timespec wait_timeout;
|
struct timespec wait_timeout;
|
||||||
|
|
||||||
if (timeout_micros < 0)
|
if (timeout_micros < 0)
|
||||||
timeout_micros= BIG_TIMEOUT;
|
timeout_micros = ONE_YEAR_IN_MICROSECS;
|
||||||
set_timespec_nsec(wait_timeout, timeout_micros * 1000);
|
set_timespec_nsec(wait_timeout, timeout_micros * 1000);
|
||||||
|
|
||||||
#ifndef STANDALONE_UNITTEST
|
#ifndef STANDALONE_UNITTEST
|
||||||
PSI_stage_info old_stage;
|
PSI_stage_info old_stage;
|
||||||
mysql_mutex_assert_owner(mutex_ptr);
|
mysql_mutex_assert_owner(mutex_ptr);
|
||||||
|
|
||||||
if (current_thd && mutex_obj->m_old_stage_info.count(current_thd) == 0)
|
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,
|
||||||
my_core::thd_enter_cond(current_thd, &m_cond, mutex_ptr,
|
&old_stage);
|
||||||
&stage_waiting_on_row_lock2, &old_stage);
|
|
||||||
/*
|
/*
|
||||||
After the mysql_cond_timedwait we need make this call
|
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,
|
to inform the SQL layer that KILLable wait has ended. However,
|
||||||
that will cause mutex to be released. Defer the release until the mutex
|
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
|
#endif
|
||||||
bool killed = false;
|
bool killed = false;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
res = mysql_cond_timedwait(&m_cond, mutex_ptr, &wait_timeout);
|
res = mysql_cond_timedwait(&m_cond, mutex_ptr, &wait_timeout);
|
||||||
|
|
||||||
#ifndef STANDALONE_UNITTEST
|
#ifndef STANDALONE_UNITTEST
|
||||||
@@ -123,7 +112,6 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
|||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@note
|
@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.
|
None of this looks like a problem for our use case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Rdb_cond_var::Notify()
|
void Rdb_cond_var::Notify() { mysql_cond_signal(&m_cond); }
|
||||||
{
|
|
||||||
mysql_cond_signal(&m_cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@note
|
@note
|
||||||
This is called without holding the mutex that's used for waiting on the
|
This is called without holding the mutex that's used for waiting on the
|
||||||
condition. See ::Notify().
|
condition. See ::Notify().
|
||||||
*/
|
*/
|
||||||
void Rdb_cond_var::NotifyAll()
|
void Rdb_cond_var::NotifyAll() { mysql_cond_broadcast(&m_cond); }
|
||||||
{
|
|
||||||
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,
|
mysql_mutex_init(0 /* Don't register in P_S. */, &m_mutex,
|
||||||
MY_MUTEX_INIT_FAST);
|
MY_MUTEX_INIT_FAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rdb_mutex::~Rdb_mutex() {
|
Rdb_mutex::~Rdb_mutex() { mysql_mutex_destroy(&m_mutex); }
|
||||||
mysql_mutex_destroy(&m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status Rdb_mutex::Lock() {
|
Status Rdb_mutex::Lock() {
|
||||||
mysql_mutex_lock(&m_mutex);
|
mysql_mutex_lock(&m_mutex);
|
||||||
@@ -192,8 +169,7 @@ Status Rdb_mutex::Lock() {
|
|||||||
// If implementing a custom version of this class, the implementation may
|
// If implementing a custom version of this class, the implementation may
|
||||||
// choose to ignore the timeout.
|
// choose to ignore the timeout.
|
||||||
// Return OK on success, or other Status on failure.
|
// 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
|
Note: PThreads API has pthread_mutex_timedlock(), but mysql's
|
||||||
mysql_mutex_* wrappers do not wrap that function.
|
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();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef STANDALONE_UNITTEST
|
#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);
|
DBUG_ASSERT(old_stage_arg != nullptr);
|
||||||
|
|
||||||
mysql_mutex_assert_owner(&m_mutex);
|
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()
|
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
|
||||||
void Rdb_mutex::UnLock() {
|
void Rdb_mutex::UnLock() {
|
||||||
#ifndef STANDALONE_UNITTEST
|
#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 =
|
const std::shared_ptr<PSI_stage_info> old_stage =
|
||||||
m_old_stage_info[current_thd];
|
m_old_stage_info[current_thd];
|
||||||
m_old_stage_info.erase(current_thd);
|
m_old_stage_info.erase(current_thd);
|
||||||
/* The following will call mysql_mutex_unlock */
|
/* 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;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -35,6 +35,7 @@ namespace myrocks {
|
|||||||
class Rdb_mutex : public rocksdb::TransactionDBMutex {
|
class Rdb_mutex : public rocksdb::TransactionDBMutex {
|
||||||
Rdb_mutex(const Rdb_mutex &p) = delete;
|
Rdb_mutex(const Rdb_mutex &p) = delete;
|
||||||
Rdb_mutex &operator=(const Rdb_mutex &p) = delete;
|
Rdb_mutex &operator=(const Rdb_mutex &p) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_mutex();
|
Rdb_mutex();
|
||||||
virtual ~Rdb_mutex();
|
virtual ~Rdb_mutex();
|
||||||
@@ -53,8 +54,8 @@ class Rdb_mutex: public rocksdb::TransactionDBMutex {
|
|||||||
// TimedOut if timed out,
|
// TimedOut if timed out,
|
||||||
// or other Status on failure.
|
// or other Status on failure.
|
||||||
// If returned status is OK, TransactionDB will eventually call UnLock().
|
// If returned status is OK, TransactionDB will eventually call UnLock().
|
||||||
virtual rocksdb::Status TryLockFor(
|
virtual rocksdb::Status
|
||||||
int64_t timeout_time __attribute__((__unused__))) override;
|
TryLockFor(int64_t timeout_time MY_ATTRIBUTE((__unused__))) override;
|
||||||
|
|
||||||
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
|
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
|
||||||
virtual void UnLock() override;
|
virtual void UnLock() override;
|
||||||
@@ -69,10 +70,10 @@ class Rdb_mutex: public rocksdb::TransactionDBMutex {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Rdb_cond_var : public rocksdb::TransactionDBCondVar {
|
class Rdb_cond_var : public rocksdb::TransactionDBCondVar {
|
||||||
Rdb_cond_var(const Rdb_cond_var &) = delete;
|
Rdb_cond_var(const Rdb_cond_var &) = delete;
|
||||||
Rdb_cond_var &operator=(const Rdb_cond_var &) = delete;
|
Rdb_cond_var &operator=(const Rdb_cond_var &) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_cond_var();
|
Rdb_cond_var();
|
||||||
virtual ~Rdb_cond_var();
|
virtual ~Rdb_cond_var();
|
||||||
@@ -116,7 +117,6 @@ class Rdb_cond_var: public rocksdb::TransactionDBCondVar {
|
|||||||
mysql_cond_t m_cond;
|
mysql_cond_t m_cond;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Rdb_mutex_factory : public rocksdb::TransactionDBMutexFactory {
|
class Rdb_mutex_factory : public rocksdb::TransactionDBMutexFactory {
|
||||||
public:
|
public:
|
||||||
Rdb_mutex_factory(const Rdb_mutex_factory &) = delete;
|
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>
|
virtual std::shared_ptr<rocksdb::TransactionDBMutex>
|
||||||
AllocateMutex() override {
|
AllocateMutex() override {
|
||||||
return
|
return std::make_shared<Rdb_mutex>();
|
||||||
std::make_shared<Rdb_mutex>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::shared_ptr<rocksdb::TransactionDBCondVar>
|
virtual std::shared_ptr<rocksdb::TransactionDBCondVar>
|
||||||
AllocateCondVar() override {
|
AllocateCondVar() override {
|
||||||
return
|
return std::make_shared<Rdb_cond_var>();
|
||||||
std::make_shared<Rdb_cond_var>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Rdb_mutex_factory() {}
|
virtual ~Rdb_mutex_factory() {}
|
||||||
|
@@ -35,8 +35,7 @@ namespace myrocks {
|
|||||||
// 2. Update sections (A), (B), and (C) below
|
// 2. Update sections (A), (B), and (C) below
|
||||||
// 3. Update perf_context.test and show_engine.test
|
// 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
|
// (A) These should be in the same order as the PC enum
|
||||||
"USER_KEY_COMPARISON_COUNT",
|
"USER_KEY_COMPARISON_COUNT",
|
||||||
"BLOCK_CACHE_HIT_COUNT",
|
"BLOCK_CACHE_HIT_COUNT",
|
||||||
@@ -80,8 +79,7 @@ std::string rdb_pc_stat_types[]=
|
|||||||
"IO_WRITE_NANOS",
|
"IO_WRITE_NANOS",
|
||||||
"IO_READ_NANOS",
|
"IO_READ_NANOS",
|
||||||
"IO_RANGE_SYNC_NANOS",
|
"IO_RANGE_SYNC_NANOS",
|
||||||
"IO_LOGGER_NANOS"
|
"IO_LOGGER_NANOS"};
|
||||||
};
|
|
||||||
|
|
||||||
#define IO_PERF_RECORD(_field_) \
|
#define IO_PERF_RECORD(_field_) \
|
||||||
do { \
|
do { \
|
||||||
@@ -96,8 +94,7 @@ std::string rdb_pc_stat_types[]=
|
|||||||
idx++; \
|
idx++; \
|
||||||
} while (0)
|
} 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
|
// (C) These should be in the same order as the PC enum
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
IO_PERF_RECORD(user_key_comparison_count);
|
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_PERF_DIFF
|
||||||
#undef IO_STAT_DIFF
|
#undef IO_STAT_DIFF
|
||||||
|
|
||||||
|
|
||||||
static Rdb_atomic_perf_counters rdb_global_perf_counters;
|
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);
|
DBUG_ASSERT(counters != nullptr);
|
||||||
|
|
||||||
counters->load(rdb_global_perf_counters);
|
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++) {
|
for (int i = 0; i < PC_MAX_IDX; i++) {
|
||||||
m_value[i] = atomic_counters.m_value[i].load(std::memory_order_relaxed);
|
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 =
|
const rocksdb::PerfLevel perf_level =
|
||||||
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
||||||
|
|
||||||
if (rocksdb::GetPerfLevel() != perf_level)
|
if (rocksdb::GetPerfLevel() != perf_level) {
|
||||||
{
|
|
||||||
rocksdb::SetPerfLevel(perf_level);
|
rocksdb::SetPerfLevel(perf_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perf_level == rocksdb::kDisable)
|
if (perf_level == rocksdb::kDisable) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,27 +176,22 @@ bool Rdb_io_perf::start(const uint32_t perf_context_level)
|
|||||||
return true;
|
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 =
|
const rocksdb::PerfLevel perf_level =
|
||||||
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
||||||
|
|
||||||
if (perf_level == rocksdb::kDisable)
|
if (perf_level == rocksdb::kDisable) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_atomic_counters)
|
if (m_atomic_counters) {
|
||||||
{
|
|
||||||
harvest_diffs(m_atomic_counters);
|
harvest_diffs(m_atomic_counters);
|
||||||
}
|
}
|
||||||
harvest_diffs(&rdb_global_perf_counters);
|
harvest_diffs(&rdb_global_perf_counters);
|
||||||
|
|
||||||
if (m_shared_io_perf_read &&
|
if (m_shared_io_perf_read && (rocksdb::perf_context.block_read_byte != 0 ||
|
||||||
(rocksdb::perf_context.block_read_byte != 0 ||
|
|
||||||
rocksdb::perf_context.block_read_count != 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;
|
my_io_perf_t io_perf_read;
|
||||||
|
|
||||||
io_perf_read.init();
|
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 (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;
|
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 +=
|
m_stats->delete_skipped +=
|
||||||
rocksdb::perf_context.internal_delete_skipped_count;
|
rocksdb::perf_context.internal_delete_skipped_count;
|
||||||
}
|
}
|
||||||
|
@@ -80,8 +80,7 @@ class Rdb_perf_counters;
|
|||||||
A collection of performance counters that can be safely incremented by
|
A collection of performance counters that can be safely incremented by
|
||||||
multiple threads since it stores atomic datapoints.
|
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];
|
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 collection of performance counters that is meant to be incremented by
|
||||||
a single thread.
|
a single thread.
|
||||||
*/
|
*/
|
||||||
class Rdb_perf_counters
|
class Rdb_perf_counters {
|
||||||
{
|
|
||||||
Rdb_perf_counters(const Rdb_perf_counters &) = delete;
|
Rdb_perf_counters(const Rdb_perf_counters &) = delete;
|
||||||
Rdb_perf_counters &operator=(const Rdb_perf_counters &) = delete;
|
Rdb_perf_counters &operator=(const Rdb_perf_counters &) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_perf_counters() = default;
|
Rdb_perf_counters() = default;
|
||||||
uint64_t m_value[PC_MAX_IDX];
|
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
|
Perf timers for data reads
|
||||||
*/
|
*/
|
||||||
class Rdb_io_perf
|
class Rdb_io_perf {
|
||||||
{
|
|
||||||
// Context management
|
// Context management
|
||||||
Rdb_atomic_perf_counters *m_atomic_counters = nullptr;
|
Rdb_atomic_perf_counters *m_atomic_counters = nullptr;
|
||||||
my_io_perf_atomic_t *m_shared_io_perf_read = 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,
|
void init(Rdb_atomic_perf_counters *const atomic_counters,
|
||||||
my_io_perf_atomic_t *const shared_io_perf_read,
|
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(atomic_counters != nullptr);
|
||||||
DBUG_ASSERT(shared_io_perf_read != nullptr);
|
DBUG_ASSERT(shared_io_perf_read != nullptr);
|
||||||
DBUG_ASSERT(stats != nullptr);
|
DBUG_ASSERT(stats != nullptr);
|
||||||
@@ -132,8 +129,8 @@ class Rdb_io_perf
|
|||||||
bool start(const uint32_t perf_context_level);
|
bool start(const uint32_t perf_context_level);
|
||||||
void end_and_record(const uint32_t perf_context_level);
|
void end_and_record(const uint32_t perf_context_level);
|
||||||
|
|
||||||
explicit Rdb_io_perf() : m_atomic_counters(nullptr),
|
explicit Rdb_io_perf()
|
||||||
m_shared_io_perf_read(nullptr),
|
: m_atomic_counters(nullptr), m_shared_io_perf_read(nullptr),
|
||||||
m_stats(nullptr) {}
|
m_stats(nullptr) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -40,20 +40,14 @@ namespace myrocks {
|
|||||||
Rdb_sst_file::Rdb_sst_file(rocksdb::DB *const db,
|
Rdb_sst_file::Rdb_sst_file(rocksdb::DB *const db,
|
||||||
rocksdb::ColumnFamilyHandle *const cf,
|
rocksdb::ColumnFamilyHandle *const cf,
|
||||||
const rocksdb::DBOptions &db_options,
|
const rocksdb::DBOptions &db_options,
|
||||||
const std::string& name, const bool tracing) :
|
const std::string &name, const bool tracing)
|
||||||
m_db(db),
|
: m_db(db), m_cf(cf), m_db_options(db_options), m_sst_file_writer(nullptr),
|
||||||
m_cf(cf),
|
m_name(name), m_tracing(tracing) {
|
||||||
m_db_options(db_options),
|
|
||||||
m_sst_file_writer(nullptr),
|
|
||||||
m_name(name),
|
|
||||||
m_tracing(tracing)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(db != nullptr);
|
DBUG_ASSERT(db != nullptr);
|
||||||
DBUG_ASSERT(cf != nullptr);
|
DBUG_ASSERT(cf != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rdb_sst_file::~Rdb_sst_file()
|
Rdb_sst_file::~Rdb_sst_file() {
|
||||||
{
|
|
||||||
// Make sure we clean up
|
// Make sure we clean up
|
||||||
delete m_sst_file_writer;
|
delete m_sst_file_writer;
|
||||||
m_sst_file_writer = nullptr;
|
m_sst_file_writer = nullptr;
|
||||||
@@ -64,15 +58,13 @@ Rdb_sst_file::~Rdb_sst_file()
|
|||||||
std::remove(m_name.c_str());
|
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);
|
DBUG_ASSERT(m_sst_file_writer == nullptr);
|
||||||
|
|
||||||
rocksdb::ColumnFamilyDescriptor cf_descr;
|
rocksdb::ColumnFamilyDescriptor cf_descr;
|
||||||
|
|
||||||
rocksdb::Status s = m_cf->GetDescriptor(&cf_descr);
|
rocksdb::Status s = m_cf->GetDescriptor(&cf_descr);
|
||||||
if (!s.ok())
|
if (!s.ok()) {
|
||||||
{
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,15 +78,13 @@ rocksdb::Status Rdb_sst_file::open()
|
|||||||
new rocksdb::SstFileWriter(env_options, options, comparator, m_cf);
|
new rocksdb::SstFileWriter(env_options, options, comparator, m_cf);
|
||||||
|
|
||||||
s = m_sst_file_writer->Open(m_name);
|
s = m_sst_file_writer->Open(m_name);
|
||||||
if (m_tracing)
|
if (m_tracing) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_information("SST Tracing: Open(%s) returned %s", m_name.c_str(),
|
sql_print_information("SST Tracing: Open(%s) returned %s", m_name.c_str(),
|
||||||
s.ok() ? "ok" : "not ok");
|
s.ok() ? "ok" : "not ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s.ok())
|
if (!s.ok()) {
|
||||||
{
|
|
||||||
delete m_sst_file_writer;
|
delete m_sst_file_writer;
|
||||||
m_sst_file_writer = nullptr;
|
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,
|
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);
|
DBUG_ASSERT(m_sst_file_writer != nullptr);
|
||||||
|
|
||||||
// Add the specified key/value to the sst file writer
|
// Add the specified key/value to the sst file writer
|
||||||
return m_sst_file_writer->Add(key, value);
|
return m_sst_file_writer->Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Rdb_sst_file::generateKey(const std::string& key)
|
std::string Rdb_sst_file::generateKey(const std::string &key) {
|
||||||
{
|
static char const hexdigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
static char const hexdigit[]= {
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
res.reserve(key.size() * 2);
|
res.reserve(key.size() * 2);
|
||||||
|
|
||||||
for (auto ch : key)
|
for (auto ch : key) {
|
||||||
{
|
|
||||||
res += hexdigit[((uint8_t)ch) >> 4];
|
res += hexdigit[((uint8_t)ch) >> 4];
|
||||||
res += hexdigit[((uint8_t)ch) & 0x0F];
|
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
|
// 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);
|
DBUG_ASSERT(m_sst_file_writer != nullptr);
|
||||||
|
|
||||||
rocksdb::Status s;
|
rocksdb::Status s;
|
||||||
@@ -141,21 +125,19 @@ rocksdb::Status Rdb_sst_file::commit()
|
|||||||
|
|
||||||
// Close out the sst file
|
// Close out the sst file
|
||||||
s = m_sst_file_writer->Finish(&fileinfo);
|
s = m_sst_file_writer->Finish(&fileinfo);
|
||||||
if (m_tracing)
|
if (m_tracing) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_information("SST Tracing: Finish returned %s",
|
sql_print_information("SST Tracing: Finish returned %s",
|
||||||
s.ok() ? "ok" : "not ok");
|
s.ok() ? "ok" : "not ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.ok())
|
if (s.ok()) {
|
||||||
{
|
if (m_tracing) {
|
||||||
if (m_tracing)
|
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_information("SST Tracing: Adding file %s, smallest key: %s, "
|
sql_print_information("SST Tracing: Adding file %s, smallest key: %s, "
|
||||||
"largest key: %s, file size: %" PRIu64 ", "
|
"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.smallest_key).c_str(),
|
||||||
generateKey(fileinfo.largest_key).c_str(),
|
generateKey(fileinfo.largest_key).c_str(),
|
||||||
fileinfo.file_size, fileinfo.num_entries);
|
fileinfo.file_size, fileinfo.num_entries);
|
||||||
@@ -171,8 +153,7 @@ rocksdb::Status Rdb_sst_file::commit()
|
|||||||
opts.allow_blocking_flush = false;
|
opts.allow_blocking_flush = false;
|
||||||
s = m_db->IngestExternalFile(m_cf, {m_name}, opts);
|
s = m_db->IngestExternalFile(m_cf, {m_name}, opts);
|
||||||
|
|
||||||
if (m_tracing)
|
if (m_tracing) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_information("SST Tracing: AddFile(%s) returned %s",
|
sql_print_information("SST Tracing: AddFile(%s) returned %s",
|
||||||
fileinfo.file_path.c_str(),
|
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,
|
const std::string &indexname,
|
||||||
rocksdb::ColumnFamilyHandle *const cf,
|
rocksdb::ColumnFamilyHandle *const cf,
|
||||||
const rocksdb::DBOptions &db_options,
|
const rocksdb::DBOptions &db_options,
|
||||||
const bool& tracing) :
|
const bool &tracing)
|
||||||
m_db(db),
|
: m_db(db), m_cf(cf), m_db_options(db_options), m_curr_size(0),
|
||||||
m_cf(cf),
|
m_sst_count(0), m_error_msg(""),
|
||||||
m_db_options(db_options),
|
|
||||||
m_curr_size(0),
|
|
||||||
m_sst_count(0),
|
|
||||||
m_error_msg(""),
|
|
||||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||||
m_queue(),
|
m_queue(), m_mutex(), m_cond(), m_thread(nullptr), m_finished(false),
|
||||||
m_mutex(),
|
|
||||||
m_cond(),
|
|
||||||
m_thread(nullptr),
|
|
||||||
m_finished(false),
|
|
||||||
#endif
|
#endif
|
||||||
m_sst_file(nullptr),
|
m_sst_file(nullptr), m_tracing(tracing) {
|
||||||
m_tracing(tracing)
|
|
||||||
{
|
|
||||||
m_prefix = db->GetName() + "/";
|
m_prefix = db->GetName() + "/";
|
||||||
|
|
||||||
std::string normalized_table;
|
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,
|
// We failed to get a normalized table name. This should never happen,
|
||||||
// but handle it anyway.
|
// but handle it anyway.
|
||||||
m_prefix += "fallback_" +
|
m_prefix += "fallback_" + std::to_string(reinterpret_cast<intptr_t>(
|
||||||
std::to_string(
|
reinterpret_cast<void *>(this))) +
|
||||||
reinterpret_cast<intptr_t>(reinterpret_cast<void*>(this))) + "_" +
|
"_" + indexname + "_";
|
||||||
indexname + "_";
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_prefix += normalized_table + "_" + indexname + "_";
|
m_prefix += normalized_table + "_" + indexname + "_";
|
||||||
}
|
}
|
||||||
|
|
||||||
rocksdb::ColumnFamilyDescriptor cf_descr;
|
rocksdb::ColumnFamilyDescriptor cf_descr;
|
||||||
const rocksdb::Status s = m_cf->GetDescriptor(&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
|
// Default size if we can't get the cf's target size
|
||||||
m_max_size = 64 * 1024 * 1024;
|
m_max_size = 64 * 1024 * 1024;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set the maximum size to 3 times the cf's target size
|
// Set the maximum size to 3 times the cf's target size
|
||||||
m_max_size = cf_descr.options.target_file_size_base * 3;
|
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);
|
DBUG_ASSERT(m_sst_file == nullptr);
|
||||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||||
DBUG_ASSERT(m_thread == nullptr);
|
DBUG_ASSERT(m_thread == nullptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int Rdb_sst_info::open_new_sst_file()
|
int Rdb_sst_info::open_new_sst_file() {
|
||||||
{
|
|
||||||
DBUG_ASSERT(m_sst_file == nullptr);
|
DBUG_ASSERT(m_sst_file == nullptr);
|
||||||
|
|
||||||
// Create the new sst file's name
|
// Create the new sst file's name
|
||||||
@@ -258,27 +220,24 @@ int Rdb_sst_info::open_new_sst_file()
|
|||||||
|
|
||||||
// Open the sst file
|
// Open the sst file
|
||||||
const rocksdb::Status s = m_sst_file->open();
|
const rocksdb::Status s = m_sst_file->open();
|
||||||
if (!s.ok())
|
if (!s.ok()) {
|
||||||
{
|
|
||||||
set_error_msg(s.ToString());
|
set_error_msg(s.ToString());
|
||||||
delete m_sst_file;
|
delete m_sst_file;
|
||||||
m_sst_file = nullptr;
|
m_sst_file = nullptr;
|
||||||
return 1;
|
return HA_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_curr_size = 0;
|
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_sst_file != nullptr);
|
||||||
DBUG_ASSERT(m_curr_size > 0);
|
DBUG_ASSERT(m_curr_size > 0);
|
||||||
|
|
||||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
#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
|
// We haven't already started a background thread, so start one
|
||||||
m_thread = new std::thread(thread_fcn, this);
|
m_thread = new std::thread(thread_fcn, this);
|
||||||
}
|
}
|
||||||
@@ -295,8 +254,7 @@ void Rdb_sst_info::close_curr_sst_file()
|
|||||||
m_cond.notify_one();
|
m_cond.notify_one();
|
||||||
#else
|
#else
|
||||||
const rocksdb::Status s = m_sst_file->commit();
|
const rocksdb::Status s = m_sst_file->commit();
|
||||||
if (!s.ok())
|
if (!s.ok()) {
|
||||||
{
|
|
||||||
set_error_msg(s.ToString());
|
set_error_msg(s.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,30 +266,24 @@ void Rdb_sst_info::close_curr_sst_file()
|
|||||||
m_curr_size = 0;
|
m_curr_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Rdb_sst_info::put(const rocksdb::Slice& key,
|
int Rdb_sst_info::put(const rocksdb::Slice &key, const rocksdb::Slice &value) {
|
||||||
const rocksdb::Slice& value)
|
|
||||||
{
|
|
||||||
int rc;
|
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
|
// The current sst file has reached its maximum, close it out
|
||||||
close_curr_sst_file();
|
close_curr_sst_file();
|
||||||
|
|
||||||
// While we are here, check to see if we have had any errors from the
|
// 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
|
// background thread - we don't want to wait for the end to report them
|
||||||
if (!m_error_msg.empty())
|
if (!m_error_msg.empty()) {
|
||||||
{
|
return HA_EXIT_FAILURE;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_curr_size == 0)
|
if (m_curr_size == 0) {
|
||||||
{
|
|
||||||
// We don't have an sst file open - open one
|
// We don't have an sst file open - open one
|
||||||
rc = open_new_sst_file();
|
rc = open_new_sst_file();
|
||||||
if (rc != 0)
|
if (rc != 0) {
|
||||||
{
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,28 +292,24 @@ int Rdb_sst_info::put(const rocksdb::Slice& key,
|
|||||||
|
|
||||||
// Add the key/value to the current sst file
|
// Add the key/value to the current sst file
|
||||||
const rocksdb::Status s = m_sst_file->put(key, value);
|
const rocksdb::Status s = m_sst_file->put(key, value);
|
||||||
if (!s.ok())
|
if (!s.ok()) {
|
||||||
{
|
|
||||||
set_error_msg(s.ToString());
|
set_error_msg(s.ToString());
|
||||||
return 1;
|
return HA_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_curr_size += key.size() + value.size();
|
m_curr_size += key.size() + value.size();
|
||||||
|
|
||||||
return 0;
|
return HA_EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Rdb_sst_info::commit()
|
int Rdb_sst_info::commit() {
|
||||||
{
|
if (m_curr_size > 0) {
|
||||||
if (m_curr_size > 0)
|
|
||||||
{
|
|
||||||
// Close out any existing files
|
// Close out any existing files
|
||||||
close_curr_sst_file();
|
close_curr_sst_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||||
if (m_thread != nullptr)
|
if (m_thread != nullptr) {
|
||||||
{
|
|
||||||
// Tell the background thread we are done
|
// Tell the background thread we are done
|
||||||
m_finished = true;
|
m_finished = true;
|
||||||
m_cond.notify_one();
|
m_cond.notify_one();
|
||||||
@@ -374,16 +322,14 @@ int Rdb_sst_info::commit()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Did we get any errors?
|
// Did we get any errors?
|
||||||
if (!m_error_msg.empty())
|
if (!m_error_msg.empty()) {
|
||||||
{
|
return HA_EXIT_FAILURE;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||||
// Both the foreground and background threads can set the error message
|
// 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
|
// 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);
|
const std::lock_guard<std::mutex> guard(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
my_printf_error(ER_UNKNOWN_ERROR, "bulk load error: %s", MYF(0), msg.c_str());
|
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;
|
m_error_msg = msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||||
// Static thread function - the Rdb_sst_info object is in 'object'
|
// 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();
|
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);
|
const std::unique_lock<std::mutex> lk(m_mutex);
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
// Wait for notification or 1 second to pass
|
// Wait for notification or 1 second to pass
|
||||||
m_cond.wait_for(lk, std::chrono::seconds(1));
|
m_cond.wait_for(lk, std::chrono::seconds(1));
|
||||||
|
|
||||||
// Inner loop pulls off all Rdb_sst_file entries and processes them
|
// 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();
|
const Rdb_sst_file *const sst_file = m_queue.front();
|
||||||
m_queue.pop();
|
m_queue.pop();
|
||||||
|
|
||||||
@@ -424,8 +365,7 @@ void Rdb_sst_info::run_thread()
|
|||||||
|
|
||||||
// Close out the sst file and add it to the database
|
// Close out the sst file and add it to the database
|
||||||
const rocksdb::Status s = sst_file->commit();
|
const rocksdb::Status s = sst_file->commit();
|
||||||
if (!s.ok())
|
if (!s.ok()) {
|
||||||
{
|
|
||||||
set_error_msg(s.ToString());
|
set_error_msg(s.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,14 +383,12 @@ void Rdb_sst_info::run_thread()
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
const std::string path = db->GetName() + FN_DIRSEP;
|
||||||
struct st_my_dir *const dir_info = my_dir(path.c_str(), MYF(MY_DONT_SORT));
|
struct st_my_dir *const dir_info = my_dir(path.c_str(), MYF(MY_DONT_SORT));
|
||||||
|
|
||||||
// Access the directory
|
// Access the directory
|
||||||
if (dir_info == nullptr)
|
if (dir_info == nullptr) {
|
||||||
{
|
|
||||||
// NO_LINT_DEBUG
|
// NO_LINT_DEBUG
|
||||||
sql_print_warning("RocksDB: Could not access database directory: %s",
|
sql_print_warning("RocksDB: Could not access database directory: %s",
|
||||||
path.c_str());
|
path.c_str());
|
||||||
@@ -459,13 +397,11 @@ void Rdb_sst_info::init(const rocksdb::DB* const db)
|
|||||||
|
|
||||||
// Scan through the files in the directory
|
// Scan through the files in the directory
|
||||||
const struct fileinfo *file_info = dir_info->dir_entry;
|
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 ...
|
// find any files ending with m_suffix ...
|
||||||
const std::string name = file_info->name;
|
const std::string name = file_info->name;
|
||||||
const size_t pos = name.find(m_suffix);
|
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
|
// ... and remove them
|
||||||
const std::string fullname = path + name;
|
const std::string fullname = path + name;
|
||||||
my_delete(fullname.c_str(), MYF(0));
|
my_delete(fullname.c_str(), MYF(0));
|
||||||
|
@@ -47,8 +47,7 @@ class Rdb_sst_file {
|
|||||||
std::string generateKey(const std::string &key);
|
std::string generateKey(const std::string &key);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Rdb_sst_file(rocksdb::DB* const db,
|
Rdb_sst_file(rocksdb::DB *const db, rocksdb::ColumnFamilyHandle *const cf,
|
||||||
rocksdb::ColumnFamilyHandle* const cf,
|
|
||||||
const rocksdb::DBOptions &db_options, const std::string &name,
|
const rocksdb::DBOptions &db_options, const std::string &name,
|
||||||
const bool tracing);
|
const bool tracing);
|
||||||
~Rdb_sst_file();
|
~Rdb_sst_file();
|
||||||
|
@@ -24,52 +24,58 @@
|
|||||||
|
|
||||||
namespace myrocks {
|
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);
|
DBUG_ASSERT(thread_ptr != nullptr);
|
||||||
Rdb_thread *const thread = static_cast<Rdb_thread *const>(thread_ptr);
|
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->run();
|
||||||
thread->uninit();
|
thread->uninit();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Rdb_thread::init(
|
void Rdb_thread::init(
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
||||||
my_core::PSI_cond_key stop_bg_psi_cond_key
|
my_core::PSI_cond_key stop_bg_psi_cond_key
|
||||||
#endif
|
#endif
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(!m_run_once);
|
DBUG_ASSERT(!m_run_once);
|
||||||
mysql_mutex_init(stop_bg_psi_mutex_key, &m_signal_mutex, MY_MUTEX_INIT_FAST);
|
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);
|
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_mutex_destroy(&m_signal_mutex);
|
||||||
mysql_cond_destroy(&m_signal_cond);
|
mysql_cond_destroy(&m_signal_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Rdb_thread::create_thread(const std::string &thread_name
|
||||||
int Rdb_thread::create_thread(
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
|
,
|
||||||
PSI_thread_key background_psi_thread_key
|
PSI_thread_key background_psi_thread_key
|
||||||
#endif
|
#endif
|
||||||
)
|
) {
|
||||||
{
|
DBUG_ASSERT(!thread_name.empty());
|
||||||
return mysql_thread_create(background_psi_thread_key,
|
|
||||||
&m_handle, nullptr, thread_func, this);
|
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);
|
mysql_mutex_lock(&m_signal_mutex);
|
||||||
if (stop_thread) {
|
if (stop_thread) {
|
||||||
m_stop = true;
|
m_stop = true;
|
||||||
|
@@ -16,6 +16,9 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/* C++ standard header files */
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/* MySQL includes */
|
/* MySQL includes */
|
||||||
#include "./my_global.h"
|
#include "./my_global.h"
|
||||||
#include <mysql/psi/mysql_table.h>
|
#include <mysql/psi/mysql_table.h>
|
||||||
@@ -26,8 +29,7 @@
|
|||||||
|
|
||||||
namespace myrocks {
|
namespace myrocks {
|
||||||
|
|
||||||
class Rdb_thread
|
class Rdb_thread {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
// Disable Copying
|
// Disable Copying
|
||||||
Rdb_thread(const Rdb_thread &);
|
Rdb_thread(const Rdb_thread &);
|
||||||
@@ -49,21 +51,18 @@ class Rdb_thread
|
|||||||
#ifdef HAVE_PSI_INTERFACE
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
void init(my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
void init(my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
||||||
my_core::PSI_cond_key stop_bg_psi_cond_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);
|
my_core::PSI_thread_key background_psi_thread_key);
|
||||||
#else
|
#else
|
||||||
void init();
|
void init();
|
||||||
int create_thread();
|
int create_thread(const std::string &thread_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void run(void) = 0;
|
virtual void run(void) = 0;
|
||||||
|
|
||||||
void signal(const bool &stop_thread = false);
|
void signal(const bool &stop_thread = false);
|
||||||
|
|
||||||
int join()
|
int join() { return pthread_join(m_handle, nullptr); }
|
||||||
{
|
|
||||||
return pthread_join(m_handle, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uninit();
|
void uninit();
|
||||||
|
|
||||||
@@ -73,20 +72,17 @@ class Rdb_thread
|
|||||||
static void *thread_func(void *const thread_ptr);
|
static void *thread_func(void *const thread_ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
MyRocks background thread control
|
MyRocks background thread control
|
||||||
N.B. This is on top of RocksDB's own background threads
|
N.B. This is on top of RocksDB's own background threads
|
||||||
(@see rocksdb::CancelAllBackgroundWork())
|
(@see rocksdb::CancelAllBackgroundWork())
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Rdb_background_thread : public Rdb_thread
|
class Rdb_background_thread : public Rdb_thread {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
bool m_save_stats = false;
|
bool m_save_stats = false;
|
||||||
|
|
||||||
void reset()
|
void reset() {
|
||||||
{
|
|
||||||
mysql_mutex_assert_owner(&m_signal_mutex);
|
mysql_mutex_assert_owner(&m_signal_mutex);
|
||||||
m_stop = false;
|
m_stop = false;
|
||||||
m_save_stats = false;
|
m_save_stats = false;
|
||||||
@@ -95,21 +91,18 @@ class Rdb_background_thread : public Rdb_thread
|
|||||||
public:
|
public:
|
||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
|
||||||
void request_save_stats()
|
void request_save_stats() {
|
||||||
{
|
|
||||||
mysql_mutex_lock(&m_signal_mutex);
|
mysql_mutex_lock(&m_signal_mutex);
|
||||||
m_save_stats = true;
|
m_save_stats = true;
|
||||||
mysql_mutex_unlock(&m_signal_mutex);
|
mysql_mutex_unlock(&m_signal_mutex);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Drop index thread control
|
Drop index thread control
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Rdb_drop_index_thread : public Rdb_thread
|
struct Rdb_drop_index_thread : public Rdb_thread {
|
||||||
{
|
|
||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -33,13 +33,11 @@ namespace myrocks {
|
|||||||
Skip past any spaces in the input
|
Skip past any spaces in the input
|
||||||
*/
|
*/
|
||||||
const char *rdb_skip_spaces(const struct charset_info_st *const cs,
|
const char *rdb_skip_spaces(const struct charset_info_st *const cs,
|
||||||
const char *str)
|
const char *str) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(cs != nullptr);
|
DBUG_ASSERT(cs != nullptr);
|
||||||
DBUG_ASSERT(str != nullptr);
|
DBUG_ASSERT(str != nullptr);
|
||||||
|
|
||||||
while (my_isspace(cs, *str))
|
while (my_isspace(cs, *str)) {
|
||||||
{
|
|
||||||
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
|
Note that str1 can be longer but we only compare up to the number
|
||||||
of characters in str2.
|
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(str1 != nullptr);
|
||||||
DBUG_ASSERT(str2 != nullptr);
|
DBUG_ASSERT(str2 != nullptr);
|
||||||
|
|
||||||
// Scan through the strings
|
// Scan through the strings
|
||||||
size_t ii;
|
size_t ii;
|
||||||
for (ii = 0; str2[ii]; ii++)
|
for (ii = 0; str2[ii]; ii++) {
|
||||||
{
|
|
||||||
if (toupper(static_cast<int>(str1[ii])) !=
|
if (toupper(static_cast<int>(str1[ii])) !=
|
||||||
toupper(static_cast<int>(str2[ii])))
|
toupper(static_cast<int>(str2[ii]))) {
|
||||||
{
|
|
||||||
return false;
|
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.
|
and skipping all data enclosed in quotes.
|
||||||
*/
|
*/
|
||||||
const char *rdb_find_in_string(const char *str, const char *pattern,
|
const char *rdb_find_in_string(const char *str, const char *pattern,
|
||||||
bool * const succeeded)
|
bool *const succeeded) {
|
||||||
{
|
|
||||||
char quote = '\0';
|
char quote = '\0';
|
||||||
bool escape = false;
|
bool escape = false;
|
||||||
|
|
||||||
@@ -86,38 +80,30 @@ const char* rdb_find_in_string(const char *str, const char *pattern,
|
|||||||
|
|
||||||
*succeeded = false;
|
*succeeded = false;
|
||||||
|
|
||||||
for ( ; *str; str++)
|
for (; *str; str++) {
|
||||||
{
|
|
||||||
/* If we found a our starting quote character */
|
/* If we found a our starting quote character */
|
||||||
if (*str == quote)
|
if (*str == quote) {
|
||||||
{
|
|
||||||
/* If it was escaped ignore it */
|
/* If it was escaped ignore it */
|
||||||
if (escape)
|
if (escape) {
|
||||||
{
|
|
||||||
escape = false;
|
escape = false;
|
||||||
}
|
}
|
||||||
/* Otherwise we are now outside of the quoted string */
|
/* Otherwise we are now outside of the quoted string */
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
quote = '\0';
|
quote = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Else if we are currently inside a quoted string? */
|
/* Else if we are currently inside a quoted string? */
|
||||||
else if (quote != '\0')
|
else if (quote != '\0') {
|
||||||
{
|
|
||||||
/* If so, check for the escape character */
|
/* If so, check for the escape character */
|
||||||
escape = !escape && *str == '\\';
|
escape = !escape && *str == '\\';
|
||||||
}
|
}
|
||||||
/* Else if we found a quote we are starting a quoted string */
|
/* Else if we found a quote we are starting a quoted string */
|
||||||
else if (*str == '"' || *str == '\'' || *str == '`')
|
else if (*str == '"' || *str == '\'' || *str == '`') {
|
||||||
{
|
|
||||||
quote = *str;
|
quote = *str;
|
||||||
}
|
}
|
||||||
/* Else we are outside of a quoted string - look for our pattern */
|
/* Else we are outside of a quoted string - look for our pattern */
|
||||||
else
|
else {
|
||||||
{
|
if (rdb_compare_strings_ic(str, pattern)) {
|
||||||
if (rdb_compare_strings_ic(str, pattern))
|
|
||||||
{
|
|
||||||
*succeeded = true;
|
*succeeded = true;
|
||||||
return str;
|
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 *rdb_check_next_token(const struct charset_info_st *const cs,
|
||||||
const char *str, const char *const pattern,
|
const char *str, const char *const pattern,
|
||||||
bool* const succeeded)
|
bool *const succeeded) {
|
||||||
{
|
|
||||||
DBUG_ASSERT(cs != nullptr);
|
DBUG_ASSERT(cs != nullptr);
|
||||||
DBUG_ASSERT(str != nullptr);
|
DBUG_ASSERT(str != nullptr);
|
||||||
DBUG_ASSERT(pattern != 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);
|
str = rdb_skip_spaces(cs, str);
|
||||||
|
|
||||||
// See if the next characters match the pattern
|
// See if the next characters match the pattern
|
||||||
if (rdb_compare_strings_ic(str, pattern))
|
if (rdb_compare_strings_ic(str, pattern)) {
|
||||||
{
|
|
||||||
*succeeded = true;
|
*succeeded = true;
|
||||||
return str + strlen(pattern);
|
return str + strlen(pattern);
|
||||||
}
|
}
|
||||||
@@ -159,42 +143,34 @@ const char* rdb_check_next_token(const struct charset_info_st* const cs,
|
|||||||
Parse id
|
Parse id
|
||||||
*/
|
*/
|
||||||
const char *rdb_parse_id(const struct charset_info_st *const cs,
|
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(cs != nullptr);
|
||||||
DBUG_ASSERT(str != nullptr);
|
DBUG_ASSERT(str != nullptr);
|
||||||
|
|
||||||
// Move past any spaces
|
// Move past any spaces
|
||||||
str = rdb_skip_spaces(cs, str);
|
str = rdb_skip_spaces(cs, str);
|
||||||
|
|
||||||
if (*str == '\0')
|
if (*str == '\0') {
|
||||||
{
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char quote = '\0';
|
char quote = '\0';
|
||||||
if (*str == '`' || *str == '"')
|
if (*str == '`' || *str == '"') {
|
||||||
{
|
|
||||||
quote = *str++;
|
quote = *str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
const char *start = str;
|
const char *start = str;
|
||||||
|
|
||||||
if (quote != '\0')
|
if (quote != '\0') {
|
||||||
{
|
for (;;) {
|
||||||
for ( ; ; )
|
if (*str == '\0') {
|
||||||
{
|
|
||||||
if (*str == '\0')
|
|
||||||
{
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*str == quote)
|
if (*str == quote) {
|
||||||
{
|
|
||||||
str++;
|
str++;
|
||||||
if (*str != quote)
|
if (*str != quote) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,27 +178,21 @@ const char* rdb_parse_id(const struct charset_info_st* const cs,
|
|||||||
str++;
|
str++;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
while (!my_isspace(cs, *str) && *str != '(' && *str != ')' && *str != '.' &&
|
||||||
{
|
*str != ',' && *str != '\0') {
|
||||||
while (!my_isspace(cs, *str) && *str != '(' && *str != ')' &&
|
|
||||||
*str != '.' && *str != ',' && *str != '\0')
|
|
||||||
{
|
|
||||||
str++;
|
str++;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user requested the id create it and return it
|
// If the user requested the id create it and return it
|
||||||
if (id != nullptr)
|
if (id != nullptr) {
|
||||||
{
|
|
||||||
*id = std::string("");
|
*id = std::string("");
|
||||||
id->reserve(len);
|
id->reserve(len);
|
||||||
while (len--)
|
while (len--) {
|
||||||
{
|
|
||||||
*id += *start;
|
*id += *start;
|
||||||
if (*start++ == quote)
|
if (*start++ == quote) {
|
||||||
{
|
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,8 +204,8 @@ const char* rdb_parse_id(const struct charset_info_st* const cs,
|
|||||||
/*
|
/*
|
||||||
Skip id
|
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(cs != nullptr);
|
||||||
DBUG_ASSERT(str != 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::size_t rdb_hex_bytes_per_char = 2;
|
||||||
static const std::array<char, 16> rdb_hexdigit =
|
static const std::array<char, 16> rdb_hexdigit = {{'0', '1', '2', '3', '4', '5',
|
||||||
{
|
'6', '7', '8', '9', 'a', 'b',
|
||||||
{ '0', '1', '2', '3', '4', '5', '6', '7',
|
'c', 'd', 'e', 'f'}};
|
||||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert data into a hex string with optional maximum length.
|
Convert data into a hex string with optional maximum length.
|
||||||
If the data is larger than the maximum length trancate it and append "..".
|
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,
|
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);
|
DBUG_ASSERT(data != nullptr);
|
||||||
|
|
||||||
// Count the elements in the string
|
// 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::size_t len = elems * rdb_hex_bytes_per_char;
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
||||||
if (maxsize != 0 && len > maxsize)
|
if (maxsize != 0 && len > maxsize) {
|
||||||
{
|
|
||||||
// If the amount of output is too large adjust the settings
|
// If the amount of output is too large adjust the settings
|
||||||
// and leave room for the ".." at the end
|
// and leave room for the ".." at the end
|
||||||
elems = (maxsize - 2) / rdb_hex_bytes_per_char;
|
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);
|
str.reserve(len);
|
||||||
|
|
||||||
// Loop through the input data and build the output string
|
// 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;
|
uint8_t ch = (uint8_t)*data;
|
||||||
str += rdb_hexdigit[ch >> 4];
|
str += rdb_hexdigit[ch >> 4];
|
||||||
str += rdb_hexdigit[ch & 0x0F];
|
str += rdb_hexdigit[ch & 0x0F];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can't fit it all add the ".."
|
// If we can't fit it all add the ".."
|
||||||
if (elems != data_len)
|
if (elems != data_len) {
|
||||||
{
|
|
||||||
str += "..";
|
str += "..";
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Attempt to access the database subdirectory to see if it exists
|
Attempt to access the database subdirectory to see if it exists
|
||||||
*/
|
*/
|
||||||
bool rdb_database_exists(const std::string& db_name)
|
bool rdb_database_exists(const std::string &db_name) {
|
||||||
{
|
const std::string dir =
|
||||||
const std::string dir = std::string(mysql_real_data_home) + FN_DIRSEP
|
std::string(mysql_real_data_home) + FN_DIRSEP + db_name;
|
||||||
+ db_name;
|
struct st_my_dir *const dir_info =
|
||||||
struct st_my_dir* const dir_info = my_dir(dir.c_str(),
|
my_dir(dir.c_str(), MYF(MY_DONT_SORT | MY_WANT_STAT));
|
||||||
MYF(MY_DONT_SORT | MY_WANT_STAT));
|
if (dir_info == nullptr) {
|
||||||
if (dir_info == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -101,6 +101,34 @@ namespace myrocks {
|
|||||||
DBUG_ASSERT(static_cast<bool>(a) == static_cast<bool>(b))
|
DBUG_ASSERT(static_cast<bool>(a) == static_cast<bool>(b))
|
||||||
#endif
|
#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.
|
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.
|
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);
|
DBUG_ASSERT(str != nullptr);
|
||||||
return reinterpret_cast<uchar *>(str->c_ptr());
|
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.
|
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());
|
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.
|
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();
|
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.
|
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);
|
DBUG_ASSERT(item != nullptr);
|
||||||
return reinterpret_cast<const uchar *>(item->data());
|
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
|
scenario for cases where it has been verified that this intervention has
|
||||||
noticeable benefits.
|
noticeable benefits.
|
||||||
*/
|
*/
|
||||||
inline int purge_all_jemalloc_arenas()
|
inline int purge_all_jemalloc_arenas() {
|
||||||
{
|
|
||||||
#ifdef HAVE_JEMALLOC
|
#ifdef HAVE_JEMALLOC
|
||||||
unsigned narenas = 0;
|
unsigned narenas = 0;
|
||||||
size_t sz = sizeof(unsigned);
|
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 *rdb_skip_spaces(const struct charset_info_st *const cs,
|
||||||
const char *str)
|
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)
|
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,
|
const char *rdb_find_in_string(const char *str, const char *pattern,
|
||||||
bool *const succeeded)
|
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 *rdb_check_next_token(const struct charset_info_st *const cs,
|
||||||
const char *str, const char *const pattern,
|
const char *str, const char *const pattern,
|
||||||
bool *const succeeded)
|
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 *rdb_parse_id(const struct charset_info_st *const cs,
|
||||||
const char *str, std::string *const id)
|
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)
|
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.
|
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,
|
std::string rdb_hexdump(const char *data, const std::size_t data_len,
|
||||||
const std::size_t maxsize = 0)
|
const std::size_t maxsize = 0)
|
||||||
__attribute__((__nonnull__));
|
MY_ATTRIBUTE((__nonnull__));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Helper function to see if a database exists
|
Helper function to see if a database exists
|
||||||
|
Reference in New Issue
Block a user