mariadb/storage/rocksdb/rdb_i_s.cc
Sergei Golubchik 9e32f229d4 plugin can signal that it cannot be unloaded by failing deinit()
if plugin->deinit() returns a failure, it is no longer ignored, it
means that the plugin isn't ready to be unloaded from memory yet.
So it's marked "dying", deinitialized as much as possible,
but stays in memory until shutdown.

also:

* increment MARIA_PLUGIN_INTERFACE_VERSION
* rewrite ha_rocksdb to use the new approach, update the test
2021-10-27 15:55:14 +02:00

1966 lines
63 KiB
C++

/*
Copyright (c) 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
#include <my_global.h>
/* C++ standard header files */
#include <algorithm>
#include <cctype>
#include <map>
#include <string>
#include <vector>
/* MySQL header files */
#include <sql_show.h>
/* RocksDB header files */
#include "rocksdb/compaction_filter.h"
#include "rocksdb/convenience.h"
#include "rocksdb/filter_policy.h"
#include "rocksdb/memtablerep.h"
#include "rocksdb/merge_operator.h"
#include "rocksdb/slice_transform.h"
#include "rocksdb/utilities/transaction_db.h"
/* MyRocks header files */
#include "./ha_rocksdb.h"
#include "./ha_rocksdb_proto.h"
#include "./rdb_cf_manager.h"
#include "./rdb_datadic.h"
#include "./rdb_utils.h"
#include "./rdb_mariadb_server_port.h"
#include "./rdb_mariadb_port.h"
namespace myrocks {
/**
Define the INFORMATION_SCHEMA (I_S) structures needed by MyRocks storage
engine.
*/
#define ROCKSDB_FIELD_INFO(_name_, _len_, _type_, _flag_) \
{ _name_, _len_, _type_, 0, _flag_, nullptr, 0 }
#define ROCKSDB_FIELD_INFO_END \
ROCKSDB_FIELD_INFO(nullptr, 0, MYSQL_TYPE_NULL, 0)
/*
Support for INFORMATION_SCHEMA.ROCKSDB_CFSTATS dynamic table
*/
namespace RDB_CFSTATS_FIELD {
enum { CF_NAME = 0, STAT_TYPE, VALUE };
} // namespace RDB_CFSTATS_FIELD
using namespace Show;
static ST_FIELD_INFO rdb_i_s_cfstats_fields_info[] = {
Column("CF_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("STAT_TYPE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("VALUE", SLonglong(), NOT_NULL),
CEnd()
};
static int rdb_i_s_cfstats_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
int ret = 0;
uint64_t val;
const std::vector<std::pair<const std::string, std::string>> cf_properties = {
{rocksdb::DB::Properties::kNumImmutableMemTable,
"NUM_IMMUTABLE_MEM_TABLE"},
{rocksdb::DB::Properties::kMemTableFlushPending,
"MEM_TABLE_FLUSH_PENDING"},
{rocksdb::DB::Properties::kCompactionPending, "COMPACTION_PENDING"},
{rocksdb::DB::Properties::kCurSizeActiveMemTable,
"CUR_SIZE_ACTIVE_MEM_TABLE"},
{rocksdb::DB::Properties::kCurSizeAllMemTables,
"CUR_SIZE_ALL_MEM_TABLES"},
{rocksdb::DB::Properties::kNumEntriesActiveMemTable,
"NUM_ENTRIES_ACTIVE_MEM_TABLE"},
{rocksdb::DB::Properties::kNumEntriesImmMemTables,
"NUM_ENTRIES_IMM_MEM_TABLES"},
{rocksdb::DB::Properties::kEstimateTableReadersMem,
"NON_BLOCK_CACHE_SST_MEM_USAGE"},
{rocksdb::DB::Properties::kNumLiveVersions, "NUM_LIVE_VERSIONS"}};
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
for (const auto &cf_name : cf_manager.get_cf_names()) {
DBUG_ASSERT(!cf_name.empty());
rocksdb::ColumnFamilyHandle *cfh = cf_manager.get_cf(cf_name);
if (cfh == nullptr) {
continue;
}
for (const auto &property : cf_properties) {
if (!rdb->GetIntProperty(cfh, property.first, &val)) {
continue;
}
tables->table->field[RDB_CFSTATS_FIELD::CF_NAME]->store(
cf_name.c_str(), cf_name.size(), system_charset_info);
tables->table->field[RDB_CFSTATS_FIELD::STAT_TYPE]->store(
property.second.c_str(), property.second.size(), system_charset_info);
tables->table->field[RDB_CFSTATS_FIELD::VALUE]->store(val, true);
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret) {
DBUG_RETURN(ret);
}
}
}
DBUG_RETURN(0);
}
static int rdb_i_s_cfstats_init(void *p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_cfstats_fields_info;
schema->fill_table = rdb_i_s_cfstats_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_DBSTATS dynamic table
*/
namespace RDB_DBSTATS_FIELD {
enum { STAT_TYPE = 0, VALUE };
} // namespace RDB_DBSTATS_FIELD
static ST_FIELD_INFO rdb_i_s_dbstats_fields_info[] = {
Column("STAT_TYPE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("VALUE", SLonglong(), NOT_NULL),
CEnd()};
static int rdb_i_s_dbstats_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
int ret = 0;
uint64_t val;
const std::vector<std::pair<std::string, std::string>> db_properties = {
{rocksdb::DB::Properties::kBackgroundErrors, "DB_BACKGROUND_ERRORS"},
{rocksdb::DB::Properties::kNumSnapshots, "DB_NUM_SNAPSHOTS"},
{rocksdb::DB::Properties::kOldestSnapshotTime,
"DB_OLDEST_SNAPSHOT_TIME"}};
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const rocksdb::BlockBasedTableOptions &table_options =
rdb_get_table_options();
for (const auto &property : db_properties) {
if (!rdb->GetIntProperty(property.first, &val)) {
continue;
}
tables->table->field[RDB_DBSTATS_FIELD::STAT_TYPE]->store(
property.second.c_str(), property.second.size(), system_charset_info);
tables->table->field[RDB_DBSTATS_FIELD::VALUE]->store(val, true);
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret) {
DBUG_RETURN(ret);
}
}
/*
Currently, this can only show the usage of a block cache allocated
directly by the handlerton. If the column family config specifies a block
cache (i.e. the column family option has a parameter such as
block_based_table_factory={block_cache=1G}), then the block cache is
allocated within the rocksdb::GetColumnFamilyOptionsFromString().
There is no interface to retrieve this block cache, nor fetch the usage
information from the column family.
*/
val = (table_options.block_cache ? table_options.block_cache->GetUsage() : 0);
tables->table->field[RDB_DBSTATS_FIELD::STAT_TYPE]->store(
STRING_WITH_LEN("DB_BLOCK_CACHE_USAGE"), system_charset_info);
tables->table->field[RDB_DBSTATS_FIELD::VALUE]->store(val, true);
ret =
static_cast<int>(my_core::schema_table_store_record(thd, tables->table));
DBUG_RETURN(ret);
}
static int rdb_i_s_dbstats_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_dbstats_fields_info;
schema->fill_table = rdb_i_s_dbstats_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_PERF_CONTEXT dynamic table
*/
namespace RDB_PERF_CONTEXT_FIELD {
enum { TABLE_SCHEMA = 0, TABLE_NAME, PARTITION_NAME, STAT_TYPE, VALUE };
} // namespace RDB_PERF_CONTEXT_FIELD
static ST_FIELD_INFO rdb_i_s_perf_context_fields_info[] = {
Column("TABLE_SCHEMA", Varchar(NAME_LEN + 1), NOT_NULL),
Column("TABLE_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("PARTITION_NAME", Varchar(NAME_LEN + 1), NULLABLE),
Column("STAT_TYPE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("VALUE", SLonglong(), NOT_NULL),
CEnd()};
static int rdb_i_s_perf_context_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
int ret = 0;
Field **field = tables->table->field;
DBUG_ASSERT(field != nullptr);
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const std::vector<std::string> tablenames = rdb_get_open_table_names();
for (const auto &it : tablenames) {
std::string str, dbname, tablename, partname;
Rdb_perf_counters counters;
int rc = rdb_normalize_tablename(it, &str);
if (rc != HA_EXIT_SUCCESS) {
DBUG_RETURN(rc);
}
if (rdb_split_normalized_tablename(str, &dbname, &tablename, &partname)) {
continue;
}
if (rdb_get_table_perf_counters(it.c_str(), &counters)) {
continue;
}
field[RDB_PERF_CONTEXT_FIELD::TABLE_SCHEMA]->store(
dbname.c_str(), dbname.size(), system_charset_info);
field[RDB_PERF_CONTEXT_FIELD::TABLE_NAME]->store(
tablename.c_str(), tablename.size(), system_charset_info);
if (partname.size() == 0) {
field[RDB_PERF_CONTEXT_FIELD::PARTITION_NAME]->set_null();
} else {
field[RDB_PERF_CONTEXT_FIELD::PARTITION_NAME]->set_notnull();
field[RDB_PERF_CONTEXT_FIELD::PARTITION_NAME]->store(
partname.c_str(), partname.size(), system_charset_info);
}
for (int i = 0; i < PC_MAX_IDX; i++) {
field[RDB_PERF_CONTEXT_FIELD::STAT_TYPE]->store(
rdb_pc_stat_types[i].c_str(), rdb_pc_stat_types[i].size(),
system_charset_info);
field[RDB_PERF_CONTEXT_FIELD::VALUE]->store(counters.m_value[i], true);
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret) {
DBUG_RETURN(ret);
}
}
}
DBUG_RETURN(0);
}
static int rdb_i_s_perf_context_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_perf_context_fields_info;
schema->fill_table = rdb_i_s_perf_context_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_PERF_CONTEXT_GLOBAL dynamic table
*/
namespace RDB_PERF_CONTEXT_GLOBAL_FIELD {
enum { STAT_TYPE = 0, VALUE };
} // namespace RDB_PERF_CONTEXT_GLOBAL_FIELD
static ST_FIELD_INFO rdb_i_s_perf_context_global_fields_info[] = {
Column("STAT_TYPE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("VALUE", SLonglong(), NOT_NULL),
CEnd()};
static int rdb_i_s_perf_context_global_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
int ret = 0;
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
// Get a copy of the global perf counters.
Rdb_perf_counters global_counters;
rdb_get_global_perf_counters(&global_counters);
for (int i = 0; i < PC_MAX_IDX; i++) {
tables->table->field[RDB_PERF_CONTEXT_GLOBAL_FIELD::STAT_TYPE]->store(
rdb_pc_stat_types[i].c_str(), rdb_pc_stat_types[i].size(),
system_charset_info);
tables->table->field[RDB_PERF_CONTEXT_GLOBAL_FIELD::VALUE]->store(
global_counters.m_value[i], true);
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret) {
DBUG_RETURN(ret);
}
}
DBUG_RETURN(0);
}
static int rdb_i_s_perf_context_global_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_perf_context_global_fields_info;
schema->fill_table = rdb_i_s_perf_context_global_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_CFOPTIONS dynamic table
*/
namespace RDB_CFOPTIONS_FIELD {
enum { CF_NAME = 0, OPTION_TYPE, VALUE };
} // namespace RDB_CFOPTIONS_FIELD
static ST_FIELD_INFO rdb_i_s_cfoptions_fields_info[] = {
Column("CF_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("OPTION_TYPE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("VALUE", Varchar(NAME_LEN + 1), NOT_NULL),
CEnd()};
static int rdb_i_s_cfoptions_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
int ret = 0;
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
for (const auto &cf_name : cf_manager.get_cf_names()) {
std::string val;
rocksdb::ColumnFamilyOptions opts;
DBUG_ASSERT(!cf_name.empty());
cf_manager.get_cf_options(cf_name, &opts);
std::vector<std::pair<std::string, std::string>> cf_option_types = {
{"COMPARATOR", opts.comparator == nullptr
? "NULL"
: std::string(opts.comparator->Name())},
{"MERGE_OPERATOR", opts.merge_operator == nullptr
? "NULL"
: std::string(opts.merge_operator->Name())},
{"COMPACTION_FILTER",
opts.compaction_filter == nullptr
? "NULL"
: std::string(opts.compaction_filter->Name())},
{"COMPACTION_FILTER_FACTORY",
opts.compaction_filter_factory == nullptr
? "NULL"
: std::string(opts.compaction_filter_factory->Name())},
{"WRITE_BUFFER_SIZE", std::to_string(opts.write_buffer_size)},
{"MAX_WRITE_BUFFER_NUMBER",
std::to_string(opts.max_write_buffer_number)},
{"MIN_WRITE_BUFFER_NUMBER_TO_MERGE",
std::to_string(opts.min_write_buffer_number_to_merge)},
{"NUM_LEVELS", std::to_string(opts.num_levels)},
{"LEVEL0_FILE_NUM_COMPACTION_TRIGGER",
std::to_string(opts.level0_file_num_compaction_trigger)},
{"LEVEL0_SLOWDOWN_WRITES_TRIGGER",
std::to_string(opts.level0_slowdown_writes_trigger)},
{"LEVEL0_STOP_WRITES_TRIGGER",
std::to_string(opts.level0_stop_writes_trigger)},
{"MAX_MEM_COMPACTION_LEVEL",
std::to_string(opts.max_mem_compaction_level)},
{"TARGET_FILE_SIZE_BASE", std::to_string(opts.target_file_size_base)},
{"TARGET_FILE_SIZE_MULTIPLIER",
std::to_string(opts.target_file_size_multiplier)},
{"MAX_BYTES_FOR_LEVEL_BASE",
std::to_string(opts.max_bytes_for_level_base)},
{"LEVEL_COMPACTION_DYNAMIC_LEVEL_BYTES",
opts.level_compaction_dynamic_level_bytes ? "ON" : "OFF"},
{"MAX_BYTES_FOR_LEVEL_MULTIPLIER",
std::to_string(opts.max_bytes_for_level_multiplier)},
{"SOFT_RATE_LIMIT", std::to_string(opts.soft_rate_limit)},
{"HARD_RATE_LIMIT", std::to_string(opts.hard_rate_limit)},
{"RATE_LIMIT_DELAY_MAX_MILLISECONDS",
std::to_string(opts.rate_limit_delay_max_milliseconds)},
{"ARENA_BLOCK_SIZE", std::to_string(opts.arena_block_size)},
{"DISABLE_AUTO_COMPACTIONS",
opts.disable_auto_compactions ? "ON" : "OFF"},
{"PURGE_REDUNDANT_KVS_WHILE_FLUSH",
opts.purge_redundant_kvs_while_flush ? "ON" : "OFF"},
{"MAX_SEQUENTIAL_SKIP_IN_ITERATIONS",
std::to_string(opts.max_sequential_skip_in_iterations)},
{"MEMTABLE_FACTORY", opts.memtable_factory == nullptr
? "NULL"
: opts.memtable_factory->Name()},
{"INPLACE_UPDATE_SUPPORT", opts.inplace_update_support ? "ON" : "OFF"},
{"INPLACE_UPDATE_NUM_LOCKS",
opts.inplace_update_num_locks ? "ON" : "OFF"},
{"MEMTABLE_PREFIX_BLOOM_BITS_RATIO",
std::to_string(opts.memtable_prefix_bloom_size_ratio)},
{"MEMTABLE_PREFIX_BLOOM_HUGE_PAGE_TLB_SIZE",
std::to_string(opts.memtable_huge_page_size)},
{"BLOOM_LOCALITY", std::to_string(opts.bloom_locality)},
{"MAX_SUCCESSIVE_MERGES", std::to_string(opts.max_successive_merges)},
{"OPTIMIZE_FILTERS_FOR_HITS",
(opts.optimize_filters_for_hits ? "ON" : "OFF")},
};
// get MAX_BYTES_FOR_LEVEL_MULTIPLIER_ADDITIONAL option value
val = opts.max_bytes_for_level_multiplier_additional.empty() ? "NULL" : "";
for (const auto &level : opts.max_bytes_for_level_multiplier_additional) {
val.append(std::to_string(level) + ":");
}
val.pop_back();
cf_option_types.push_back(
{"MAX_BYTES_FOR_LEVEL_MULTIPLIER_ADDITIONAL", val});
// get COMPRESSION_TYPE option value
GetStringFromCompressionType(&val, opts.compression);
if (val.empty()) {
val = "NULL";
}
cf_option_types.push_back({"COMPRESSION_TYPE", val});
// get COMPRESSION_PER_LEVEL option value
val = opts.compression_per_level.empty() ? "NULL" : "";
for (const auto &compression_type : opts.compression_per_level) {
std::string res;
GetStringFromCompressionType(&res, compression_type);
if (!res.empty()) {
val.append(res + ":");
}
}
val.pop_back();
cf_option_types.push_back({"COMPRESSION_PER_LEVEL", val});
// get compression_opts value
val = std::to_string(opts.compression_opts.window_bits) + ":";
val.append(std::to_string(opts.compression_opts.level) + ":");
val.append(std::to_string(opts.compression_opts.strategy));
cf_option_types.push_back({"COMPRESSION_OPTS", val});
// bottommost_compression
if (opts.bottommost_compression) {
std::string res;
GetStringFromCompressionType(&res, opts.bottommost_compression);
if (!res.empty()) {
cf_option_types.push_back({"BOTTOMMOST_COMPRESSION", res});
}
}
// get PREFIX_EXTRACTOR option
cf_option_types.push_back(
{"PREFIX_EXTRACTOR", opts.prefix_extractor == nullptr
? "NULL"
: std::string(opts.prefix_extractor->Name())});
// get COMPACTION_STYLE option
switch (opts.compaction_style) {
case rocksdb::kCompactionStyleLevel:
val = "kCompactionStyleLevel";
break;
case rocksdb::kCompactionStyleUniversal:
val = "kCompactionStyleUniversal";
break;
case rocksdb::kCompactionStyleFIFO:
val = "kCompactionStyleFIFO";
break;
case rocksdb::kCompactionStyleNone:
val = "kCompactionStyleNone";
break;
default:
val = "NULL";
}
cf_option_types.push_back({"COMPACTION_STYLE", val});
// get COMPACTION_OPTIONS_UNIVERSAL related options
const rocksdb::CompactionOptionsUniversal compac_opts =
opts.compaction_options_universal;
val = "{SIZE_RATIO=";
val.append(std::to_string(compac_opts.size_ratio));
val.append("; MIN_MERGE_WIDTH=");
val.append(std::to_string(compac_opts.min_merge_width));
val.append("; MAX_MERGE_WIDTH=");
val.append(std::to_string(compac_opts.max_merge_width));
val.append("; MAX_SIZE_AMPLIFICATION_PERCENT=");
val.append(std::to_string(compac_opts.max_size_amplification_percent));
val.append("; COMPRESSION_SIZE_PERCENT=");
val.append(std::to_string(compac_opts.compression_size_percent));
val.append("; STOP_STYLE=");
switch (compac_opts.stop_style) {
case rocksdb::kCompactionStopStyleSimilarSize:
val.append("kCompactionStopStyleSimilarSize}");
break;
case rocksdb::kCompactionStopStyleTotalSize:
val.append("kCompactionStopStyleTotalSize}");
break;
default:
val.append("}");
}
cf_option_types.push_back({"COMPACTION_OPTIONS_UNIVERSAL", val});
// get COMPACTION_OPTION_FIFO option
cf_option_types.push_back(
{"COMPACTION_OPTION_FIFO::MAX_TABLE_FILES_SIZE",
std::to_string(opts.compaction_options_fifo.max_table_files_size)});
// get table related options
std::vector<std::string> table_options =
split_into_vector(opts.table_factory->GetPrintableTableOptions(), '\n');
for (auto option : table_options) {
option.erase(std::remove(option.begin(), option.end(), ' '),
option.end());
int pos = option.find(":");
std::string option_name = option.substr(0, pos);
std::string option_value = option.substr(pos + 1, option.length());
std::transform(option_name.begin(), option_name.end(),
option_name.begin(),
[](unsigned char c) { return std::toupper(c); });
cf_option_types.push_back(
{"TABLE_FACTORY::" + option_name, option_value});
}
for (const auto &cf_option_type : cf_option_types) {
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
tables->table->field[RDB_CFOPTIONS_FIELD::CF_NAME]->store(
cf_name.c_str(), cf_name.size(), system_charset_info);
tables->table->field[RDB_CFOPTIONS_FIELD::OPTION_TYPE]->store(
cf_option_type.first.c_str(), cf_option_type.first.size(),
system_charset_info);
tables->table->field[RDB_CFOPTIONS_FIELD::VALUE]->store(
cf_option_type.second.c_str(), cf_option_type.second.size(),
system_charset_info);
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret) {
DBUG_RETURN(ret);
}
}
}
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO dynamic table
*/
namespace RDB_GLOBAL_INFO_FIELD {
enum { TYPE = 0, NAME, VALUE };
}
static ST_FIELD_INFO rdb_i_s_global_info_fields_info[] = {
Column("TYPE", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("NAME", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("VALUE", Varchar(FN_REFLEN + 1), NOT_NULL),
CEnd()};
/*
* helper function for rdb_i_s_global_info_fill_table
* to insert (TYPE, KEY, VALUE) rows into
* information_schema.rocksdb_global_info
*/
static int rdb_global_info_fill_row(my_core::THD *const thd,
my_core::TABLE_LIST *const tables,
const char *const type,
const char *const name,
const char *const value) {
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(type != nullptr);
DBUG_ASSERT(name != nullptr);
DBUG_ASSERT(value != nullptr);
Field **field = tables->table->field;
DBUG_ASSERT(field != nullptr);
field[RDB_GLOBAL_INFO_FIELD::TYPE]->store(type, strlen(type),
system_charset_info);
field[RDB_GLOBAL_INFO_FIELD::NAME]->store(name, strlen(name),
system_charset_info);
field[RDB_GLOBAL_INFO_FIELD::VALUE]->store(value, strlen(value),
system_charset_info);
return my_core::schema_table_store_record(thd, tables->table);
}
static int rdb_i_s_global_info_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
static const uint32_t INT_BUF_LEN = 21;
static const uint32_t CF_ID_INDEX_BUF_LEN = 60;
int ret = 0;
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
/* binlog info */
Rdb_binlog_manager *const blm = rdb_get_binlog_manager();
DBUG_ASSERT(blm != nullptr);
char file_buf[FN_REFLEN + 1] = {0};
my_off_t pos = 0;
char pos_buf[INT_BUF_LEN] = {0};
char gtid_buf[GTID_BUF_LEN] = {0};
if (blm->read(file_buf, &pos, gtid_buf)) {
snprintf(pos_buf, INT_BUF_LEN, "%llu", (ulonglong)pos);
ret |= rdb_global_info_fill_row(thd, tables, "BINLOG", "FILE", file_buf);
ret |= rdb_global_info_fill_row(thd, tables, "BINLOG", "POS", pos_buf);
ret |= rdb_global_info_fill_row(thd, tables, "BINLOG", "GTID", gtid_buf);
}
/* max index info */
const Rdb_dict_manager *const dict_manager = rdb_get_dict_manager();
DBUG_ASSERT(dict_manager != nullptr);
uint32_t max_index_id;
char max_index_id_buf[INT_BUF_LEN] = {0};
if (dict_manager->get_max_index_id(&max_index_id)) {
snprintf(max_index_id_buf, INT_BUF_LEN, "%u", max_index_id);
ret |= rdb_global_info_fill_row(thd, tables, "MAX_INDEX_ID", "MAX_INDEX_ID",
max_index_id_buf);
}
/* cf_id -> cf_flags */
char cf_id_buf[INT_BUF_LEN] = {0};
char cf_value_buf[FN_REFLEN + 1] = {0};
const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
for (const auto &cf_handle : cf_manager.get_all_cf()) {
DBUG_ASSERT(cf_handle != nullptr);
uint flags;
if (!dict_manager->get_cf_flags(cf_handle->GetID(), &flags)) {
// NO_LINT_DEBUG
sql_print_error(
"RocksDB: Failed to get column family flags "
"from CF with id = %u. MyRocks data dictionary may "
"be corrupted.",
cf_handle->GetID());
abort();
}
snprintf(cf_id_buf, INT_BUF_LEN, "%u", cf_handle->GetID());
snprintf(cf_value_buf, FN_REFLEN, "%s [%u]", cf_handle->GetName().c_str(),
flags);
ret |= rdb_global_info_fill_row(thd, tables, "CF_FLAGS", cf_id_buf,
cf_value_buf);
if (ret) {
break;
}
}
/* DDL_DROP_INDEX_ONGOING */
std::unordered_set<GL_INDEX_ID> gl_index_ids;
dict_manager->get_ongoing_index_operation(
&gl_index_ids, Rdb_key_def::DDL_DROP_INDEX_ONGOING);
char cf_id_index_buf[CF_ID_INDEX_BUF_LEN] = {0};
for (auto gl_index_id : gl_index_ids) {
snprintf(cf_id_index_buf, CF_ID_INDEX_BUF_LEN, "cf_id:%u,index_id:%u",
gl_index_id.cf_id, gl_index_id.index_id);
ret |= rdb_global_info_fill_row(thd, tables, "DDL_DROP_INDEX_ONGOING",
cf_id_index_buf, "");
if (ret) {
break;
}
}
DBUG_RETURN(ret);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS dynamic table
*/
static int rdb_i_s_compact_stats_fill_table(
my_core::THD *thd, my_core::TABLE_LIST *tables,
my_core::Item *cond MY_ATTRIBUTE((__unused__))) {
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ENTER_FUNC();
int ret = 0;
rocksdb::DB *rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
for (auto cf_name : cf_manager.get_cf_names()) {
rocksdb::ColumnFamilyHandle *cfh = cf_manager.get_cf(cf_name);
if (cfh == nullptr) {
continue;
}
std::map<std::string, std::string> props;
bool bool_ret MY_ATTRIBUTE((__unused__));
bool_ret = rdb->GetMapProperty(cfh, "rocksdb.cfstats", &props);
DBUG_ASSERT(bool_ret);
const std::string prop_name_prefix = "compaction.";
for (auto const &prop_ent : props) {
std::string prop_name = prop_ent.first;
if (prop_name.find(prop_name_prefix) != 0) {
continue;
}
std::string value = prop_ent.second;
std::size_t del_pos = prop_name.find('.', prop_name_prefix.size());
DBUG_ASSERT(del_pos != std::string::npos);
std::string level_str = prop_name.substr(
prop_name_prefix.size(), del_pos - prop_name_prefix.size());
std::string type_str = prop_name.substr(del_pos + 1);
Field **field = tables->table->field;
DBUG_ASSERT(field != nullptr);
field[0]->store(cf_name.c_str(), cf_name.size(), system_charset_info);
field[1]->store(level_str.c_str(), level_str.size(), system_charset_info);
field[2]->store(type_str.c_str(), type_str.size(), system_charset_info);
field[3]->store(std::stod(value));
ret |= static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret != 0) {
DBUG_RETURN(ret);
}
}
}
DBUG_RETURN(ret);
}
static ST_FIELD_INFO rdb_i_s_compact_stats_fields_info[] = {
Column("CF_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("LEVEL", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("TYPE", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("VALUE", Double(MY_INT64_NUM_DECIMAL_DIGITS), NOT_NULL),
CEnd()};
namespace // anonymous namespace = not visible outside this source file
{
struct Rdb_ddl_scanner : public Rdb_tables_scanner {
my_core::THD *m_thd;
my_core::TABLE *m_table;
int add_table(Rdb_tbl_def *tdef) override;
};
} // anonymous namespace
/*
Support for INFORMATION_SCHEMA.ROCKSDB_DDL dynamic table
*/
namespace RDB_DDL_FIELD {
enum {
TABLE_SCHEMA = 0,
TABLE_NAME,
PARTITION_NAME,
INDEX_NAME,
COLUMN_FAMILY,
INDEX_NUMBER,
INDEX_TYPE,
KV_FORMAT_VERSION,
TTL_DURATION,
INDEX_FLAGS,
CF,
AUTO_INCREMENT
};
} // namespace RDB_DDL_FIELD
static ST_FIELD_INFO rdb_i_s_ddl_fields_info[] = {
Column("TABLE_SCHEMA", Varchar(NAME_LEN + 1), NOT_NULL),
Column("TABLE_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("PARTITION_NAME", Varchar(NAME_LEN + 1), NULLABLE),
Column("INDEX_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("COLUMN_FAMILY", SLong(), NOT_NULL),
Column("INDEX_NUMBER", SLong(), NOT_NULL),
Column("INDEX_TYPE", SShort(6), NOT_NULL),
Column("KV_FORMAT_VERSION", SShort(6), NOT_NULL),
Column("TTL_DURATION", SLonglong(), NOT_NULL),
Column("INDEX_FLAGS", SLonglong(), NOT_NULL),
Column("CF", Varchar(NAME_LEN + 1), NOT_NULL),
Column("AUTO_INCREMENT", ULonglong(), NULLABLE),
CEnd()};
int Rdb_ddl_scanner::add_table(Rdb_tbl_def *tdef) {
DBUG_ASSERT(tdef != nullptr);
int ret = 0;
DBUG_ASSERT(m_table != nullptr);
Field **field = m_table->field;
DBUG_ASSERT(field != nullptr);
const Rdb_dict_manager *dict_manager = rdb_get_dict_manager();
const std::string &dbname = tdef->base_dbname();
field[RDB_DDL_FIELD::TABLE_SCHEMA]->store(dbname.c_str(), dbname.size(),
system_charset_info);
const std::string &tablename = tdef->base_tablename();
field[RDB_DDL_FIELD::TABLE_NAME]->store(tablename.c_str(), tablename.size(),
system_charset_info);
const std::string &partname = tdef->base_partition();
if (partname.length() == 0) {
field[RDB_DDL_FIELD::PARTITION_NAME]->set_null();
} else {
field[RDB_DDL_FIELD::PARTITION_NAME]->set_notnull();
field[RDB_DDL_FIELD::PARTITION_NAME]->store(
partname.c_str(), partname.size(), system_charset_info);
}
for (uint i = 0; i < tdef->m_key_count; i++) {
const Rdb_key_def &kd = *tdef->m_key_descr_arr[i];
field[RDB_DDL_FIELD::INDEX_NAME]->store(kd.m_name.c_str(), kd.m_name.size(),
system_charset_info);
GL_INDEX_ID gl_index_id = kd.get_gl_index_id();
field[RDB_DDL_FIELD::COLUMN_FAMILY]->store(gl_index_id.cf_id, true);
field[RDB_DDL_FIELD::INDEX_NUMBER]->store(gl_index_id.index_id, true);
field[RDB_DDL_FIELD::INDEX_TYPE]->store(kd.m_index_type, true);
field[RDB_DDL_FIELD::KV_FORMAT_VERSION]->store(kd.m_kv_format_version,
true);
field[RDB_DDL_FIELD::TTL_DURATION]->store(kd.m_ttl_duration, true);
field[RDB_DDL_FIELD::INDEX_FLAGS]->store(kd.m_index_flags_bitmap, true);
std::string cf_name = kd.get_cf()->GetName();
field[RDB_DDL_FIELD::CF]->store(cf_name.c_str(), cf_name.size(),
system_charset_info);
ulonglong auto_incr;
if (dict_manager->get_auto_incr_val(tdef->get_autoincr_gl_index_id(),
&auto_incr)) {
field[RDB_DDL_FIELD::AUTO_INCREMENT]->set_notnull();
field[RDB_DDL_FIELD::AUTO_INCREMENT]->store(auto_incr, true);
} else {
field[RDB_DDL_FIELD::AUTO_INCREMENT]->set_null();
}
ret = my_core::schema_table_store_record(m_thd, m_table);
if (ret) return ret;
}
return HA_EXIT_SUCCESS;
}
static int rdb_i_s_ddl_fill_table(my_core::THD *const thd,
my_core::TABLE_LIST *const tables,
my_core::Item *const cond) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
int ret = 0;
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
Rdb_ddl_scanner ddl_arg;
ddl_arg.m_thd = thd;
ddl_arg.m_table = tables->table;
Rdb_ddl_manager *ddl_manager = rdb_get_ddl_manager();
DBUG_ASSERT(ddl_manager != nullptr);
ret = ddl_manager->scan_for_tables(&ddl_arg);
DBUG_RETURN(ret);
}
static int rdb_i_s_ddl_init(void *const p) {
DBUG_ENTER_FUNC();
my_core::ST_SCHEMA_TABLE *schema;
DBUG_ASSERT(p != nullptr);
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_ddl_fields_info;
schema->fill_table = rdb_i_s_ddl_fill_table;
DBUG_RETURN(0);
}
static int rdb_i_s_cfoptions_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_cfoptions_fields_info;
schema->fill_table = rdb_i_s_cfoptions_fill_table;
DBUG_RETURN(0);
}
static int rdb_i_s_global_info_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = reinterpret_cast<my_core::ST_SCHEMA_TABLE *>(p);
schema->fields_info = rdb_i_s_global_info_fields_info;
schema->fill_table = rdb_i_s_global_info_fill_table;
DBUG_RETURN(0);
}
static int rdb_i_s_compact_stats_init(void *p) {
my_core::ST_SCHEMA_TABLE *schema;
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
schema = reinterpret_cast<my_core::ST_SCHEMA_TABLE *>(p);
schema->fields_info = rdb_i_s_compact_stats_fields_info;
schema->fill_table = rdb_i_s_compact_stats_fill_table;
DBUG_RETURN(0);
}
/* Given a path to a file return just the filename portion. */
static std::string rdb_filename_without_path(const std::string &path) {
/* Find last slash in path */
const size_t pos = path.rfind('/');
/* None found? Just return the original string */
if (pos == std::string::npos) {
return std::string(path);
}
/* Return everything after the slash (or backslash) */
return path.substr(pos + 1);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_SST_PROPS dynamic table
*/
namespace RDB_SST_PROPS_FIELD {
enum {
SST_NAME = 0,
COLUMN_FAMILY,
DATA_BLOCKS,
ENTRIES,
RAW_KEY_SIZE,
RAW_VALUE_SIZE,
DATA_BLOCK_SIZE,
INDEX_BLOCK_SIZE,
INDEX_PARTITIONS,
TOP_LEVEL_INDEX_SIZE,
FILTER_BLOCK_SIZE,
COMPRESSION_ALGO,
CREATION_TIME,
FILE_CREATION_TIME,
OLDEST_KEY_TIME,
FILTER_POLICY,
COMPRESSION_OPTIONS,
};
} // namespace RDB_SST_PROPS_FIELD
static ST_FIELD_INFO rdb_i_s_sst_props_fields_info[] = {
Column("SST_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("COLUMN_FAMILY", SLong(), NOT_NULL),
Column("DATA_BLOCKS", SLonglong(), NOT_NULL),
Column("ENTRIES", SLonglong(), NOT_NULL),
Column("RAW_KEY_SIZE", SLonglong(), NOT_NULL),
Column("RAW_VALUE_SIZE", SLonglong(), NOT_NULL),
Column("DATA_BLOCK_SIZE", SLonglong(), NOT_NULL),
Column("INDEX_BLOCK_SIZE", SLonglong(), NOT_NULL),
Column("INDEX_PARTITIONS", SLong(), NOT_NULL),
Column("TOP_LEVEL_INDEX_SIZE", SLonglong(), NOT_NULL),
Column("FILTER_BLOCK_SIZE", SLonglong(), NOT_NULL),
Column("COMPRESSION_ALGO", Varchar(NAME_LEN + 1), NOT_NULL),
Column("CREATION_TIME", SLonglong(), NOT_NULL),
Column("FILE_CREATION_TIME", SLonglong(), NOT_NULL),
Column("OLDEST_KEY_TIME", SLonglong(), NOT_NULL),
Column("FILTER_POLICY", Varchar(NAME_LEN + 1), NOT_NULL),
Column("COMPRESSION_OPTIONS", Varchar(NAME_LEN + 1), NOT_NULL),
CEnd()};
static int rdb_i_s_sst_props_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
int ret = 0;
Field **field = tables->table->field;
DBUG_ASSERT(field != nullptr);
/* Iterate over all the column families */
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
for (const auto &cf_handle : cf_manager.get_all_cf()) {
/* Grab the the properties of all the tables in the column family */
rocksdb::TablePropertiesCollection table_props_collection;
const rocksdb::Status s =
rdb->GetPropertiesOfAllTables(cf_handle, &table_props_collection);
if (!s.ok()) {
continue;
}
/* Iterate over all the items in the collection, each of which contains a
* name and the actual properties */
for (const auto &props : table_props_collection) {
/* Add the SST name into the output */
const std::string sst_name = rdb_filename_without_path(props.first);
field[RDB_SST_PROPS_FIELD::SST_NAME]->store(
sst_name.data(), sst_name.size(), system_charset_info);
field[RDB_SST_PROPS_FIELD::COLUMN_FAMILY]->store(
props.second->column_family_id, true);
field[RDB_SST_PROPS_FIELD::DATA_BLOCKS]->store(
props.second->num_data_blocks, true);
field[RDB_SST_PROPS_FIELD::ENTRIES]->store(props.second->num_entries,
true);
field[RDB_SST_PROPS_FIELD::RAW_KEY_SIZE]->store(
props.second->raw_key_size, true);
field[RDB_SST_PROPS_FIELD::RAW_VALUE_SIZE]->store(
props.second->raw_value_size, true);
field[RDB_SST_PROPS_FIELD::DATA_BLOCK_SIZE]->store(
props.second->data_size, true);
field[RDB_SST_PROPS_FIELD::INDEX_BLOCK_SIZE]->store(
props.second->index_size, true);
field[RDB_SST_PROPS_FIELD::INDEX_PARTITIONS]->store(
props.second->index_partitions, true);
field[RDB_SST_PROPS_FIELD::TOP_LEVEL_INDEX_SIZE]->store(
props.second->top_level_index_size, true);
field[RDB_SST_PROPS_FIELD::FILTER_BLOCK_SIZE]->store(
props.second->filter_size, true);
if (props.second->compression_name.empty()) {
field[RDB_SST_PROPS_FIELD::COMPRESSION_ALGO]->set_null();
} else {
field[RDB_SST_PROPS_FIELD::COMPRESSION_ALGO]->store(
props.second->compression_name.c_str(),
props.second->compression_name.size(), system_charset_info);
}
field[RDB_SST_PROPS_FIELD::CREATION_TIME]->store(
props.second->creation_time, true);
field[RDB_SST_PROPS_FIELD::FILE_CREATION_TIME]->store(
props.second->file_creation_time, true);
field[RDB_SST_PROPS_FIELD::OLDEST_KEY_TIME]->store(
props.second->oldest_key_time, true);
if (props.second->filter_policy_name.empty()) {
field[RDB_SST_PROPS_FIELD::FILTER_POLICY]->set_null();
} else {
field[RDB_SST_PROPS_FIELD::FILTER_POLICY]->store(
props.second->filter_policy_name.c_str(),
props.second->filter_policy_name.size(), system_charset_info);
}
if (props.second->compression_options.empty()) {
field[RDB_SST_PROPS_FIELD::COMPRESSION_OPTIONS]->set_null();
} else {
field[RDB_SST_PROPS_FIELD::COMPRESSION_OPTIONS]->store(
props.second->compression_options.c_str(),
props.second->compression_options.size(), system_charset_info);
}
/* Tell MySQL about this row in the virtual table */
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret != 0) {
DBUG_RETURN(ret);
}
}
}
DBUG_RETURN(ret);
}
/* Initialize the information_schema.rocksdb_sst_props virtual table */
static int rdb_i_s_sst_props_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_sst_props_fields_info;
schema->fill_table = rdb_i_s_sst_props_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP dynamic table
*/
namespace RDB_INDEX_FILE_MAP_FIELD {
enum {
COLUMN_FAMILY = 0,
INDEX_NUMBER,
SST_NAME,
NUM_ROWS,
DATA_SIZE,
ENTRY_DELETES,
ENTRY_SINGLEDELETES,
ENTRY_MERGES,
ENTRY_OTHERS,
DISTINCT_KEYS_PREFIX
};
} // namespace RDB_INDEX_FILE_MAP_FIELD
static ST_FIELD_INFO rdb_i_s_index_file_map_fields_info[] = {
/* The information_schema.rocksdb_index_file_map virtual table has four
* fields:
* COLUMN_FAMILY => the index's column family contained in the SST file
* INDEX_NUMBER => the index id contained in the SST file
* SST_NAME => the name of the SST file containing some indexes
* NUM_ROWS => the number of entries of this index id in this SST file
* DATA_SIZE => the data size stored in this SST file for this index id */
Column("COLUMN_FAMILY", SLong(), NOT_NULL),
Column("INDEX_NUMBER", SLong(), NOT_NULL),
Column("SST_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("NUM_ROWS", SLonglong(), NOT_NULL),
Column("DATA_SIZE", SLonglong(), NOT_NULL),
Column("ENTRY_DELETES", SLonglong(), NOT_NULL),
Column("ENTRY_SINGLEDELETES", SLonglong(), NOT_NULL),
Column("ENTRY_MERGES", SLonglong(), NOT_NULL),
Column("ENTRY_OTHERS", SLonglong(), NOT_NULL),
Column("DISTINCT_KEYS_PREFIX",Varchar(MAX_REF_PARTS * 25), NOT_NULL),
CEnd()};
/* Fill the information_schema.rocksdb_index_file_map virtual table */
static int rdb_i_s_index_file_map_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
int ret = 0;
Field **field = tables->table->field;
DBUG_ASSERT(field != nullptr);
/* Iterate over all the column families */
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
for (const auto &cf_handle : cf_manager.get_all_cf()) {
/* Grab the the properties of all the tables in the column family */
rocksdb::TablePropertiesCollection table_props_collection;
const rocksdb::Status s =
rdb->GetPropertiesOfAllTables(cf_handle, &table_props_collection);
if (!s.ok()) {
continue;
}
/* Iterate over all the items in the collection, each of which contains a
* name and the actual properties */
for (const auto &props : table_props_collection) {
/* Add the SST name into the output */
const std::string sst_name = rdb_filename_without_path(props.first);
field[RDB_INDEX_FILE_MAP_FIELD::SST_NAME]->store(
sst_name.data(), sst_name.size(), system_charset_info);
/* Get the __indexstats__ data out of the table property */
std::vector<Rdb_index_stats> stats;
Rdb_tbl_prop_coll::read_stats_from_tbl_props(props.second, &stats);
if (stats.empty()) {
field[RDB_INDEX_FILE_MAP_FIELD::COLUMN_FAMILY]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::INDEX_NUMBER]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::NUM_ROWS]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::DATA_SIZE]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_DELETES]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_SINGLEDELETES]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_MERGES]->store(-1, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_OTHERS]->store(-1, true);
} else {
for (const auto &it : stats) {
/* Add the index number, the number of rows, and data size to the
* output */
field[RDB_INDEX_FILE_MAP_FIELD::COLUMN_FAMILY]->store(
it.m_gl_index_id.cf_id, true);
field[RDB_INDEX_FILE_MAP_FIELD::INDEX_NUMBER]->store(
it.m_gl_index_id.index_id, true);
field[RDB_INDEX_FILE_MAP_FIELD::NUM_ROWS]->store(it.m_rows, true);
field[RDB_INDEX_FILE_MAP_FIELD::DATA_SIZE]->store(it.m_data_size,
true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_DELETES]->store(
it.m_entry_deletes, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_SINGLEDELETES]->store(
it.m_entry_single_deletes, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_MERGES]->store(
it.m_entry_merges, true);
field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_OTHERS]->store(
it.m_entry_others, true);
std::string distinct_keys_prefix;
for (size_t i = 0; i < it.m_distinct_keys_per_prefix.size(); i++) {
if (i > 0) {
distinct_keys_prefix += ",";
}
distinct_keys_prefix +=
std::to_string(it.m_distinct_keys_per_prefix[i]);
}
field[RDB_INDEX_FILE_MAP_FIELD::DISTINCT_KEYS_PREFIX]->store(
distinct_keys_prefix.data(), distinct_keys_prefix.size(),
system_charset_info);
/* Tell MySQL about this row in the virtual table */
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret != 0) {
break;
}
}
}
}
}
DBUG_RETURN(ret);
}
/* Initialize the information_schema.rocksdb_index_file_map virtual table */
static int rdb_i_s_index_file_map_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_index_file_map_fields_info;
schema->fill_table = rdb_i_s_index_file_map_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_LOCKS dynamic table
*/
namespace RDB_LOCKS_FIELD {
enum { COLUMN_FAMILY_ID = 0, TRANSACTION_ID, KEY, MODE };
} // namespace RDB_LOCKS_FIELD
static ST_FIELD_INFO rdb_i_s_lock_info_fields_info[] = {
Column("COLUMN_FAMILY_ID", SLong(), NOT_NULL),
Column("TRANSACTION_ID", SLong(), NOT_NULL),
Column("KEY", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("MODE", Varchar(32), NOT_NULL),
CEnd()};
/* Fill the information_schema.rocksdb_locks virtual table */
static int rdb_i_s_lock_info_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
int ret = 0;
rocksdb::TransactionDB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
/* cf id -> rocksdb::KeyLockInfo */
std::unordered_multimap<uint32_t, rocksdb::KeyLockInfo> lock_info =
rdb->GetLockStatusData();
for (const auto &lock : lock_info) {
const uint32_t cf_id = lock.first;
const auto &key_lock_info = lock.second;
const auto key_hexstr = rdb_hexdump(key_lock_info.key.c_str(),
key_lock_info.key.length(), FN_REFLEN);
for (const auto &id : key_lock_info.ids) {
tables->table->field[RDB_LOCKS_FIELD::COLUMN_FAMILY_ID]->store(cf_id,
true);
tables->table->field[RDB_LOCKS_FIELD::TRANSACTION_ID]->store(id, true);
tables->table->field[RDB_LOCKS_FIELD::KEY]->store(
key_hexstr.c_str(), key_hexstr.size(), system_charset_info);
tables->table->field[RDB_LOCKS_FIELD::MODE]->store(
key_lock_info.exclusive ? "X" : "S", 1, system_charset_info);
/* Tell MySQL about this row in the virtual table */
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret != 0) {
break;
}
}
}
DBUG_RETURN(ret);
}
/* Initialize the information_schema.rocksdb_lock_info virtual table */
static int rdb_i_s_lock_info_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_lock_info_fields_info;
schema->fill_table = rdb_i_s_lock_info_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_TRX dynamic table
*/
namespace RDB_TRX_FIELD {
enum {
TRANSACTION_ID = 0,
STATE,
NAME,
WRITE_COUNT,
LOCK_COUNT,
TIMEOUT_SEC,
WAITING_KEY,
WAITING_COLUMN_FAMILY_ID,
IS_REPLICATION,
SKIP_TRX_API,
READ_ONLY,
HAS_DEADLOCK_DETECTION,
NUM_ONGOING_BULKLOAD,
THREAD_ID,
QUERY
};
} // namespace RDB_TRX_FIELD
static ST_FIELD_INFO rdb_i_s_trx_info_fields_info[] = {
Column("TRANSACTION_ID", SLonglong(), NOT_NULL),
Column("STATE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("WRITE_COUNT", SLonglong(), NOT_NULL),
Column("LOCK_COUNT", SLonglong(), NOT_NULL),
Column("TIMEOUT_SEC", SLong(), NOT_NULL),
Column("WAITING_KEY", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("WAITING_COLUMN_FAMILY_ID",SLong(), NOT_NULL),
Column("IS_REPLICATION", SLong(), NOT_NULL),
Column("SKIP_TRX_API", SLong(), NOT_NULL),
Column("READ_ONLY", SLong(), NOT_NULL),
Column("HAS_DEADLOCK_DETECTION", SLong(), NOT_NULL),
Column("NUM_ONGOING_BULKLOAD", SLong(), NOT_NULL),
Column("THREAD_ID", SLong(), NOT_NULL),
Column("QUERY", Varchar(NAME_LEN + 1), NOT_NULL),
CEnd()};
/* Fill the information_schema.rocksdb_trx virtual table */
static int rdb_i_s_trx_info_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
int ret = 0;
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const std::vector<Rdb_trx_info> &all_trx_info = rdb_get_all_trx_info();
for (const auto &info : all_trx_info) {
auto name_hexstr =
rdb_hexdump(info.name.c_str(), info.name.length(), NAME_LEN);
auto key_hexstr = rdb_hexdump(info.waiting_key.c_str(),
info.waiting_key.length(), FN_REFLEN);
tables->table->field[RDB_TRX_FIELD::TRANSACTION_ID]->store(info.trx_id,
true);
tables->table->field[RDB_TRX_FIELD::STATE]->store(
info.state.c_str(), info.state.length(), system_charset_info);
tables->table->field[RDB_TRX_FIELD::NAME]->store(
name_hexstr.c_str(), name_hexstr.length(), system_charset_info);
tables->table->field[RDB_TRX_FIELD::WRITE_COUNT]->store(info.write_count,
true);
tables->table->field[RDB_TRX_FIELD::LOCK_COUNT]->store(info.lock_count,
true);
tables->table->field[RDB_TRX_FIELD::TIMEOUT_SEC]->store(info.timeout_sec,
false);
tables->table->field[RDB_TRX_FIELD::WAITING_KEY]->store(
key_hexstr.c_str(), key_hexstr.length(), system_charset_info);
tables->table->field[RDB_TRX_FIELD::WAITING_COLUMN_FAMILY_ID]->store(
info.waiting_cf_id, true);
tables->table->field[RDB_TRX_FIELD::IS_REPLICATION]->store(
info.is_replication, false);
tables->table->field[RDB_TRX_FIELD::SKIP_TRX_API]->store(info.skip_trx_api,
false);
tables->table->field[RDB_TRX_FIELD::READ_ONLY]->store(info.read_only,
false);
tables->table->field[RDB_TRX_FIELD::HAS_DEADLOCK_DETECTION]->store(
info.deadlock_detect, false);
tables->table->field[RDB_TRX_FIELD::NUM_ONGOING_BULKLOAD]->store(
info.num_ongoing_bulk_load, false);
tables->table->field[RDB_TRX_FIELD::THREAD_ID]->store(info.thread_id, true);
tables->table->field[RDB_TRX_FIELD::QUERY]->store(
info.query_str.c_str(), info.query_str.length(), system_charset_info);
/* Tell MySQL about this row in the virtual table */
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret != 0) {
break;
}
}
DBUG_RETURN(ret);
}
/* Initialize the information_schema.rocksdb_trx_info virtual table */
static int rdb_i_s_trx_info_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_trx_info_fields_info;
schema->fill_table = rdb_i_s_trx_info_fill_table;
DBUG_RETURN(0);
}
/*
Support for INFORMATION_SCHEMA.ROCKSDB_DEADLOCK dynamic table
*/
namespace RDB_DEADLOCK_FIELD {
enum {
DEADLOCK_ID = 0,
TIMESTAMP,
TRANSACTION_ID,
CF_NAME,
WAITING_KEY,
LOCK_TYPE,
INDEX_NAME,
TABLE_NAME,
ROLLED_BACK,
};
} // namespace RDB_DEADLOCK_FIELD
static ST_FIELD_INFO rdb_i_s_deadlock_info_fields_info[] = {
Column("DEADLOCK_ID", SLonglong(), NOT_NULL),
Column("TIMESTAMP", SLonglong(), NOT_NULL),
Column("TRANSACTION_ID", SLonglong(), NOT_NULL),
Column("CF_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("WAITING_KEY", Varchar(FN_REFLEN + 1), NOT_NULL),
Column("LOCK_TYPE", Varchar(NAME_LEN + 1), NOT_NULL),
Column("INDEX_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("TABLE_NAME", Varchar(NAME_LEN + 1), NOT_NULL),
Column("ROLLED_BACK", SLonglong(), NOT_NULL),
CEnd()};
/* Fill the information_schema.rocksdb_trx virtual table */
static int rdb_i_s_deadlock_info_fill_table(
my_core::THD *const thd, my_core::TABLE_LIST *const tables,
my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(thd != nullptr);
DBUG_ASSERT(tables != nullptr);
DBUG_ASSERT(tables->table != nullptr);
DBUG_ASSERT(tables->table->field != nullptr);
static const std::string str_exclusive("EXCLUSIVE");
static const std::string str_shared("SHARED");
int ret = 0;
rocksdb::DB *const rdb = rdb_get_rocksdb_db();
if (!rdb) {
DBUG_RETURN(ret);
}
const std::vector<Rdb_deadlock_info> &all_dl_info = rdb_get_deadlock_info();
ulonglong id = 0;
for (const auto &info : all_dl_info) {
auto deadlock_time = info.deadlock_time;
for (const auto &trx_info : info.path) {
tables->table->field[RDB_DEADLOCK_FIELD::DEADLOCK_ID]->store(id, true);
tables->table->field[RDB_DEADLOCK_FIELD::TIMESTAMP]->store(deadlock_time,
true);
tables->table->field[RDB_DEADLOCK_FIELD::TRANSACTION_ID]->store(
trx_info.trx_id, true);
tables->table->field[RDB_DEADLOCK_FIELD::CF_NAME]->store(
trx_info.cf_name.c_str(), trx_info.cf_name.length(),
system_charset_info);
tables->table->field[RDB_DEADLOCK_FIELD::WAITING_KEY]->store(
trx_info.waiting_key.c_str(), trx_info.waiting_key.length(),
system_charset_info);
if (trx_info.exclusive_lock) {
tables->table->field[RDB_DEADLOCK_FIELD::LOCK_TYPE]->store(
str_exclusive.c_str(), str_exclusive.length(), system_charset_info);
} else {
tables->table->field[RDB_DEADLOCK_FIELD::LOCK_TYPE]->store(
str_shared.c_str(), str_shared.length(), system_charset_info);
}
tables->table->field[RDB_DEADLOCK_FIELD::INDEX_NAME]->store(
trx_info.index_name.c_str(), trx_info.index_name.length(),
system_charset_info);
tables->table->field[RDB_DEADLOCK_FIELD::TABLE_NAME]->store(
trx_info.table_name.c_str(), trx_info.table_name.length(),
system_charset_info);
tables->table->field[RDB_DEADLOCK_FIELD::ROLLED_BACK]->store(
trx_info.trx_id == info.victim_trx_id, true);
/* Tell MySQL about this row in the virtual table */
ret = static_cast<int>(
my_core::schema_table_store_record(thd, tables->table));
if (ret != 0) {
break;
}
}
id++;
}
DBUG_RETURN(ret);
}
/* Initialize the information_schema.rocksdb_trx_info virtual table */
static int rdb_i_s_deadlock_info_init(void *const p) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(p != nullptr);
my_core::ST_SCHEMA_TABLE *schema;
schema = (my_core::ST_SCHEMA_TABLE *)p;
schema->fields_info = rdb_i_s_deadlock_info_fields_info;
schema->fill_table = rdb_i_s_deadlock_info_fill_table;
DBUG_RETURN(0);
}
static int rdb_i_s_deinit(void *p MY_ATTRIBUTE((__unused__))) {
DBUG_ENTER_FUNC();
/* see the comment at the end of rocksdb_done_func() */
DBUG_RETURN(1);
}
static struct st_mysql_information_schema rdb_i_s_info = {
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
struct st_maria_plugin rdb_i_s_cfstats = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_CFSTATS",
"Facebook",
"RocksDB column family stats",
PLUGIN_LICENSE_GPL,
rdb_i_s_cfstats_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_dbstats = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_DBSTATS",
"Facebook",
"RocksDB database stats",
PLUGIN_LICENSE_GPL,
rdb_i_s_dbstats_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_perf_context = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_PERF_CONTEXT",
"Facebook",
"RocksDB perf context stats",
PLUGIN_LICENSE_GPL,
rdb_i_s_perf_context_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_perf_context_global = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_PERF_CONTEXT_GLOBAL",
"Facebook",
"RocksDB perf context stats (all)",
PLUGIN_LICENSE_GPL,
rdb_i_s_perf_context_global_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_cfoptions = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_CF_OPTIONS",
"Facebook",
"RocksDB column family options",
PLUGIN_LICENSE_GPL,
rdb_i_s_cfoptions_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_global_info = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_GLOBAL_INFO",
"Facebook",
"RocksDB global info",
PLUGIN_LICENSE_GPL,
rdb_i_s_global_info_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_compact_stats = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_COMPACTION_STATS",
"Facebook",
"RocksDB compaction stats",
PLUGIN_LICENSE_GPL,
rdb_i_s_compact_stats_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_ddl = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_DDL",
"Facebook",
"RocksDB Data Dictionary",
PLUGIN_LICENSE_GPL,
rdb_i_s_ddl_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_sst_props = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_SST_PROPS",
"Facebook",
"RocksDB SST Properties",
PLUGIN_LICENSE_GPL,
rdb_i_s_sst_props_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_index_file_map = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_INDEX_FILE_MAP",
"Facebook",
"RocksDB index file map",
PLUGIN_LICENSE_GPL,
rdb_i_s_index_file_map_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_lock_info = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_LOCKS",
"Facebook",
"RocksDB lock information",
PLUGIN_LICENSE_GPL,
rdb_i_s_lock_info_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_trx_info = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_TRX",
"Facebook",
"RocksDB transaction information",
PLUGIN_LICENSE_GPL,
rdb_i_s_trx_info_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
struct st_maria_plugin rdb_i_s_deadlock_info = {
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&rdb_i_s_info,
"ROCKSDB_DEADLOCK",
"Facebook",
"RocksDB transaction information",
PLUGIN_LICENSE_GPL,
rdb_i_s_deadlock_info_init,
rdb_i_s_deinit,
0x0001, /* version number (0.1) */
nullptr, /* status variables */
nullptr, /* system variables */
nullptr, /* config options */
MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
};
} // namespace myrocks