mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01: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:
parent
cfb59f3196
commit
7468ccfadf
82 changed files with 9204 additions and 10486 deletions
|
@ -22,8 +22,8 @@
|
|||
#include <vector>
|
||||
|
||||
/* MySQL includes */
|
||||
#include <mysql/plugin.h>
|
||||
#include <my_global.h>
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
/* MyRocks includes */
|
||||
#include "./ha_rocksdb.h"
|
||||
|
@ -33,10 +33,8 @@
|
|||
namespace myrocks {
|
||||
|
||||
static std::vector<Rdb_index_stats>
|
||||
extract_index_stats(
|
||||
const std::vector<std::string>& files,
|
||||
const rocksdb::TablePropertiesCollection& props
|
||||
) {
|
||||
extract_index_stats(const std::vector<std::string> &files,
|
||||
const rocksdb::TablePropertiesCollection &props) {
|
||||
std::vector<Rdb_index_stats> ret;
|
||||
for (auto fn : files) {
|
||||
const auto it = props.find(fn);
|
||||
|
@ -49,11 +47,10 @@ extract_index_stats(
|
|||
}
|
||||
|
||||
void Rdb_event_listener::update_index_stats(
|
||||
const rocksdb::TableProperties& props
|
||||
) {
|
||||
const rocksdb::TableProperties &props) {
|
||||
DBUG_ASSERT(m_ddl_manager != nullptr);
|
||||
const auto tbl_props =
|
||||
std::make_shared<const rocksdb::TableProperties>(props);
|
||||
std::make_shared<const rocksdb::TableProperties>(props);
|
||||
|
||||
std::vector<Rdb_index_stats> stats;
|
||||
Rdb_tbl_prop_coll::read_stats_from_tbl_props(tbl_props, &stats);
|
||||
|
@ -62,32 +59,26 @@ void Rdb_event_listener::update_index_stats(
|
|||
}
|
||||
|
||||
void Rdb_event_listener::OnCompactionCompleted(
|
||||
rocksdb::DB *db,
|
||||
const rocksdb::CompactionJobInfo& ci
|
||||
) {
|
||||
rocksdb::DB *db, const rocksdb::CompactionJobInfo &ci) {
|
||||
DBUG_ASSERT(db != nullptr);
|
||||
DBUG_ASSERT(m_ddl_manager != nullptr);
|
||||
|
||||
if (ci.status.ok()) {
|
||||
m_ddl_manager->adjust_stats(
|
||||
extract_index_stats(ci.output_files, ci.table_properties),
|
||||
extract_index_stats(ci.input_files, ci.table_properties));
|
||||
extract_index_stats(ci.output_files, ci.table_properties),
|
||||
extract_index_stats(ci.input_files, ci.table_properties));
|
||||
}
|
||||
}
|
||||
|
||||
void Rdb_event_listener::OnFlushCompleted(
|
||||
rocksdb::DB* db,
|
||||
const rocksdb::FlushJobInfo& flush_job_info
|
||||
) {
|
||||
rocksdb::DB *db, const rocksdb::FlushJobInfo &flush_job_info) {
|
||||
DBUG_ASSERT(db != nullptr);
|
||||
update_index_stats(flush_job_info.table_properties);
|
||||
}
|
||||
|
||||
void Rdb_event_listener::OnExternalFileIngested(
|
||||
rocksdb::DB* db,
|
||||
const rocksdb::ExternalFileIngestionInfo& info
|
||||
) {
|
||||
rocksdb::DB *db, const rocksdb::ExternalFileIngestionInfo &info) {
|
||||
DBUG_ASSERT(db != nullptr);
|
||||
update_index_stats(info.table_properties);
|
||||
}
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -21,29 +21,26 @@ namespace myrocks {
|
|||
|
||||
class Rdb_ddl_manager;
|
||||
|
||||
class Rdb_event_listener : public rocksdb::EventListener
|
||||
{
|
||||
public:
|
||||
Rdb_event_listener(const Rdb_event_listener&) = delete;
|
||||
Rdb_event_listener& operator=(const Rdb_event_listener&) = delete;
|
||||
class Rdb_event_listener : public rocksdb::EventListener {
|
||||
public:
|
||||
Rdb_event_listener(const Rdb_event_listener &) = delete;
|
||||
Rdb_event_listener &operator=(const Rdb_event_listener &) = delete;
|
||||
|
||||
explicit Rdb_event_listener(Rdb_ddl_manager* const ddl_manager) :
|
||||
m_ddl_manager(ddl_manager) {
|
||||
}
|
||||
explicit Rdb_event_listener(Rdb_ddl_manager *const ddl_manager)
|
||||
: m_ddl_manager(ddl_manager) {}
|
||||
|
||||
void OnCompactionCompleted(
|
||||
rocksdb::DB* db, const rocksdb::CompactionJobInfo& ci) override;
|
||||
void OnFlushCompleted(
|
||||
rocksdb::DB* db, const rocksdb::FlushJobInfo& flush_job_info) override;
|
||||
void OnCompactionCompleted(rocksdb::DB *db,
|
||||
const rocksdb::CompactionJobInfo &ci) override;
|
||||
void OnFlushCompleted(rocksdb::DB *db,
|
||||
const rocksdb::FlushJobInfo &flush_job_info) override;
|
||||
void OnExternalFileIngested(
|
||||
rocksdb::DB* db, const rocksdb::ExternalFileIngestionInfo& ingestion_info)
|
||||
override;
|
||||
rocksdb::DB *db,
|
||||
const rocksdb::ExternalFileIngestionInfo &ingestion_info) override;
|
||||
|
||||
private:
|
||||
Rdb_ddl_manager* m_ddl_manager;
|
||||
private:
|
||||
Rdb_ddl_manager *m_ddl_manager;
|
||||
|
||||
void update_index_stats(
|
||||
const rocksdb::TableProperties& props);
|
||||
void update_index_stats(const rocksdb::TableProperties &props);
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -32,27 +32,31 @@ enum RDB_IO_ERROR_TYPE {
|
|||
RDB_IO_ERROR_TX_COMMIT,
|
||||
RDB_IO_ERROR_DICT_COMMIT,
|
||||
RDB_IO_ERROR_BG_THREAD,
|
||||
RDB_IO_ERROR_GENERAL
|
||||
RDB_IO_ERROR_GENERAL,
|
||||
RDB_IO_ERROR_LAST
|
||||
};
|
||||
|
||||
void rdb_handle_io_error(rocksdb::Status status, RDB_IO_ERROR_TYPE err_type);
|
||||
const char *get_rdb_io_error_string(const RDB_IO_ERROR_TYPE err_type);
|
||||
|
||||
int rdb_normalize_tablename(const std::string& tablename, std::string* str)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
void rdb_handle_io_error(const rocksdb::Status status,
|
||||
const RDB_IO_ERROR_TYPE err_type);
|
||||
|
||||
int rdb_split_normalized_tablename(const std::string& fullname, std::string *db,
|
||||
int rdb_normalize_tablename(const std::string &tablename, std::string *str)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int rdb_split_normalized_tablename(const std::string &fullname, std::string *db,
|
||||
std::string *table = nullptr,
|
||||
std::string *partition = nullptr)
|
||||
__attribute__((__warn_unused_result__));
|
||||
MY_ATTRIBUTE((__warn_unused_result__));
|
||||
|
||||
std::vector<std::string> rdb_get_open_table_names(void);
|
||||
|
||||
int rdb_get_table_perf_counters(const char *tablename,
|
||||
Rdb_perf_counters *counters)
|
||||
__attribute__((__nonnull__(2)));
|
||||
MY_ATTRIBUTE((__nonnull__(2)));
|
||||
|
||||
void rdb_get_global_perf_counters(Rdb_perf_counters *counters)
|
||||
__attribute__((__nonnull__(1)));
|
||||
MY_ATTRIBUTE((__nonnull__(1)));
|
||||
|
||||
void rdb_queue_save_stats_request();
|
||||
|
||||
|
@ -63,20 +67,20 @@ void rdb_queue_save_stats_request();
|
|||
rocksdb::TransactionDB *rdb_get_rocksdb_db();
|
||||
|
||||
class Rdb_cf_manager;
|
||||
Rdb_cf_manager& rdb_get_cf_manager();
|
||||
Rdb_cf_manager &rdb_get_cf_manager();
|
||||
|
||||
rocksdb::BlockBasedTableOptions& rdb_get_table_options();
|
||||
rocksdb::BlockBasedTableOptions &rdb_get_table_options();
|
||||
|
||||
class Rdb_dict_manager;
|
||||
Rdb_dict_manager *rdb_get_dict_manager(void)
|
||||
__attribute__((__warn_unused_result__));
|
||||
MY_ATTRIBUTE((__warn_unused_result__));
|
||||
|
||||
class Rdb_ddl_manager;
|
||||
Rdb_ddl_manager *rdb_get_ddl_manager(void)
|
||||
__attribute__((__warn_unused_result__));
|
||||
MY_ATTRIBUTE((__warn_unused_result__));
|
||||
|
||||
class Rdb_binlog_manager;
|
||||
Rdb_binlog_manager *rdb_get_binlog_manager(void)
|
||||
__attribute__((__warn_unused_result__));
|
||||
MY_ATTRIBUTE((__warn_unused_result__));
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -21,13 +21,10 @@
|
|||
|
||||
namespace myrocks {
|
||||
|
||||
class Rdb_logger : public rocksdb::Logger
|
||||
{
|
||||
public:
|
||||
void Logv(const rocksdb::InfoLogLevel log_level,
|
||||
const char* format,
|
||||
va_list ap) override
|
||||
{
|
||||
class Rdb_logger : public rocksdb::Logger {
|
||||
public:
|
||||
void Logv(const rocksdb::InfoLogLevel log_level, const char *format,
|
||||
va_list ap) override {
|
||||
DBUG_ASSERT(format != nullptr);
|
||||
|
||||
enum loglevel mysql_log_level;
|
||||
|
@ -41,11 +38,11 @@ class Rdb_logger : public rocksdb::Logger
|
|||
}
|
||||
|
||||
if (log_level >= rocksdb::InfoLogLevel::ERROR_LEVEL) {
|
||||
mysql_log_level= ERROR_LEVEL;
|
||||
mysql_log_level = ERROR_LEVEL;
|
||||
} else if (log_level >= rocksdb::InfoLogLevel::WARN_LEVEL) {
|
||||
mysql_log_level= WARNING_LEVEL;
|
||||
mysql_log_level = WARNING_LEVEL;
|
||||
} else {
|
||||
mysql_log_level= INFORMATION_LEVEL;
|
||||
mysql_log_level = INFORMATION_LEVEL;
|
||||
}
|
||||
|
||||
// log to MySQL
|
||||
|
@ -54,20 +51,18 @@ class Rdb_logger : public rocksdb::Logger
|
|||
error_log_print(mysql_log_level, f.c_str(), ap);
|
||||
}
|
||||
|
||||
void Logv(const char* format, va_list ap) override
|
||||
{
|
||||
void Logv(const char *format, va_list ap) override {
|
||||
DBUG_ASSERT(format != nullptr);
|
||||
// If no level is specified, it is by default at information level
|
||||
Logv(rocksdb::InfoLogLevel::INFO_LEVEL, format, ap);
|
||||
}
|
||||
|
||||
void SetRocksDBLogger(const std::shared_ptr<rocksdb::Logger> logger)
|
||||
{
|
||||
void SetRocksDBLogger(const std::shared_ptr<rocksdb::Logger> logger) {
|
||||
m_logger = logger;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::shared_ptr<rocksdb::Logger> m_logger;
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -4,20 +4,20 @@ CREATE DATABASE mysqlslap;
|
|||
USE mysqlslap;
|
||||
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
|
||||
# 2PC enabled, MyRocks durability enabled
|
||||
SET GLOBAL rocksdb_disable_2pc=0;
|
||||
SET GLOBAL rocksdb_enable_2pc=0;
|
||||
SET GLOBAL rocksdb_write_sync=1;
|
||||
## 2PC + durability + single thread
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
select case when variable_value-@c = 1000 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
case when variable_value-@c = 1000 then 'true' else 'false' end
|
||||
true
|
||||
false
|
||||
## 2PC + durability + group commit
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
select case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true' else 'false' end
|
||||
true
|
||||
false
|
||||
# 2PC enabled, MyRocks durability disabled
|
||||
SET GLOBAL rocksdb_disable_2pc=0;
|
||||
SET GLOBAL rocksdb_enable_2pc=0;
|
||||
SET GLOBAL rocksdb_write_sync=0;
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
select case when variable_value-@c = 0 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
|
@ -28,17 +28,17 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
|
|||
case when variable_value-@c = 0 then 'true' else 'false' end
|
||||
true
|
||||
# 2PC disabled, MyRocks durability enabled
|
||||
SET GLOBAL rocksdb_disable_2pc=1;
|
||||
SET GLOBAL rocksdb_enable_2pc=1;
|
||||
SET GLOBAL rocksdb_write_sync=1;
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
select case when variable_value-@c = 0 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
case when variable_value-@c = 0 then 'true' else 'false' end
|
||||
true
|
||||
false
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
select case when variable_value-@c = 0 then 'true' else 'false' end from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
case when variable_value-@c = 0 then 'true' else 'false' end
|
||||
true
|
||||
SET GLOBAL rocksdb_disable_2pc=1;
|
||||
false
|
||||
SET GLOBAL rocksdb_enable_2pc=1;
|
||||
SET GLOBAL rocksdb_write_sync=0;
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE mysqlslap;
|
||||
|
|
|
@ -60,11 +60,8 @@ CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i), KEY(j)) ENGINE = ROCKSDB
|
|||
# crash_during_index_creation_partition
|
||||
flush logs;
|
||||
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
|
||||
# expected assertion failure from sql layer here for alter rollback
|
||||
call mtr.add_suppression("Assertion `0' failed.");
|
||||
call mtr.add_suppression("Attempting backtrace. You can use the following information to find out");
|
||||
ALTER TABLE t1 ADD INDEX kij(i,j), ALGORITHM=INPLACE;
|
||||
ERROR HY000: Lost connection to MySQL server during query
|
||||
ERROR HY000: Intentional failure in inplace alter occurred.
|
||||
SET SESSION debug="-d,myrocks_simulate_index_create_rollback";
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
|
|
|
@ -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 =
|
||||
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
||||
WHERE TABLE_NAME = 't1' AND INDEX_NAME = "PRIMARY");
|
||||
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS
|
||||
# # SSTNAME 5 # # # # #
|
||||
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
|
||||
# # SSTNAME 5 # # # # # 5
|
||||
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
||||
WHERE INDEX_NUMBER =
|
||||
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
||||
WHERE TABLE_NAME = 't1' AND INDEX_NAME = "j");
|
||||
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS
|
||||
# # SSTNAME 5 # # # # #
|
||||
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
|
||||
# # SSTNAME 5 # # # # # 5,5
|
||||
SELECT * FROM INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP
|
||||
WHERE INDEX_NUMBER =
|
||||
(SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.ROCKSDB_DDL
|
||||
WHERE TABLE_NAME = 't2' AND INDEX_NAME = "PRIMARY");
|
||||
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS
|
||||
# # SSTNAME 4 # # # # #
|
||||
COLUMN_FAMILY INDEX_NUMBER SST_NAME NUM_ROWS DATA_SIZE ENTRY_DELETES ENTRY_SINGLEDELETES ENTRY_MERGES ENTRY_OTHERS DISTINCT_KEYS_PREFIX
|
||||
# # SSTNAME 4 # # # # # 4
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
|
|
|
@ -9,6 +9,7 @@ CF_FLAGS 1 __system__ [0]
|
|||
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||
count(*)
|
||||
3
|
||||
select VALUE into @keysIn from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
|
||||
CREATE TABLE t1 (i1 INT, i2 INT, PRIMARY KEY (i1)) ENGINE = ROCKSDB;
|
||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
||||
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||
|
@ -22,6 +23,11 @@ CF_FLAGS 1 __system__ [0]
|
|||
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||
count(*)
|
||||
6
|
||||
set global rocksdb_force_flush_memtable_now = true;
|
||||
set global rocksdb_compact_cf='default';
|
||||
select case when VALUE-@keysIn >= 3 then 'true' else 'false' end from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
|
||||
case when VALUE-@keysIn >= 3 then 'true' else 'false' end
|
||||
true
|
||||
CREATE INDEX tindex1 on t1 (i1);
|
||||
CREATE INDEX tindex2 on t1 (i2);
|
||||
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where TYPE = 'CF_FLAGS';
|
||||
|
|
|
@ -121,7 +121,7 @@ a b
|
|||
5 loaded
|
||||
7 test
|
||||
DROP TABLE t1;
|
||||
set session rocksdb_skip_unique_check=1;
|
||||
set session unique_checks=0;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (a INT, b CHAR(8), pk INT AUTO_INCREMENT PRIMARY KEY) ENGINE=rocksdb;
|
||||
LOAD DATA INFILE '<DATADIR>/se_loaddata.dat' INTO TABLE t1
|
||||
|
|
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_default_cf_options
|
||||
rocksdb_delete_obsolete_files_period_micros 21600000000
|
||||
rocksdb_disable_2pc ON
|
||||
rocksdb_disabledatasync OFF
|
||||
rocksdb_enable_2pc ON
|
||||
rocksdb_enable_bulk_load_api ON
|
||||
rocksdb_enable_thread_tracking OFF
|
||||
rocksdb_enable_write_thread_adaptive_yield OFF
|
||||
|
@ -924,17 +924,17 @@ rocksdb_override_cf_options
|
|||
rocksdb_paranoid_checks ON
|
||||
rocksdb_pause_background_work ON
|
||||
rocksdb_perf_context_level 0
|
||||
rocksdb_persistent_cache_path
|
||||
rocksdb_persistent_cache_size 0
|
||||
rocksdb_pin_l0_filter_and_index_blocks_in_cache ON
|
||||
rocksdb_print_snapshot_conflict_queries OFF
|
||||
rocksdb_rate_limiter_bytes_per_sec 0
|
||||
rocksdb_read_free_rpl_tables
|
||||
rocksdb_records_in_range 50
|
||||
rocksdb_rpl_skip_tx_api OFF
|
||||
rocksdb_seconds_between_stat_computes 3600
|
||||
rocksdb_signal_drop_index_thread OFF
|
||||
rocksdb_skip_bloom_filter_on_read OFF
|
||||
rocksdb_skip_fill_cache OFF
|
||||
rocksdb_skip_unique_check OFF
|
||||
rocksdb_skip_unique_check_tables .*
|
||||
rocksdb_stats_dump_period_sec 600
|
||||
rocksdb_store_row_debug_checksums OFF
|
||||
|
@ -2231,7 +2231,7 @@ DROP DATABASE test_db;
|
|||
# Issue #143: Split rocksdb_bulk_load option into two
|
||||
#
|
||||
CREATE TABLE t1 (id int primary key, value int) engine=RocksDB;
|
||||
SET rocksdb_skip_unique_check=1;
|
||||
SET unique_checks=0;
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(1, 3);
|
||||
|
@ -2243,7 +2243,7 @@ INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1;
|
|||
ERROR HY000: When unique checking is disabled in MyRocks, INSERT,UPDATE,LOAD statements with clauses that update or replace the key (i.e. INSERT ON DUPLICATE KEY UPDATE, REPLACE) are not allowed. Query: INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1
|
||||
TRUNCATE TABLE t1;
|
||||
SET @save_rocksdb_bulk_load_size= @@rocksdb_bulk_load_size;
|
||||
SET rocksdb_skip_unique_check=0;
|
||||
SET unique_checks=1;
|
||||
SET rocksdb_commit_in_the_middle=1;
|
||||
SET rocksdb_bulk_load_size=10;
|
||||
BEGIN;
|
||||
|
|
|
@ -6,9 +6,9 @@ Note #### Storing MySQL user name or password information in the master info rep
|
|||
DROP TABLE IF EXISTS t1;
|
||||
include/stop_slave.inc
|
||||
create table t1 (a int) engine=rocksdb;
|
||||
show variables like 'rocksdb_rpl_skip_tx_api';
|
||||
show variables like 'rpl_skip_tx_api';
|
||||
Variable_name Value
|
||||
rocksdb_rpl_skip_tx_api ON
|
||||
rpl_skip_tx_api ON
|
||||
include/start_slave.inc
|
||||
found
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -183,3 +183,24 @@ ERROR 23000: Duplicate entry '1-1' for key 'PRIMARY'
|
|||
INSERT INTO t2 VALUES (2,1);
|
||||
ERROR 23000: Duplicate entry '1' for key 'a'
|
||||
DROP TABLE t2;
|
||||
#
|
||||
# Issue #491 (https://github.com/facebook/mysql-5.6/issues/491)
|
||||
#
|
||||
CREATE TABLE t (a BLOB, PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
|
||||
INSERT INTO t VALUES('a');
|
||||
CHECK TABLE t EXTENDED;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a), UNIQUE KEY (a(1))) engine=rocksdb;
|
||||
INSERT INTO t VALUES('a');
|
||||
CHECK TABLE t EXTENDED;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
|
||||
INSERT INTO t VALUES('a');
|
||||
CHECK TABLE t EXTENDED;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
DROP TABLE t;
|
||||
|
|
|
@ -13,7 +13,7 @@ USE mysqlslap;
|
|||
CREATE TABLE t1(id BIGINT AUTO_INCREMENT, value BIGINT, PRIMARY KEY(id)) ENGINE=rocksdb;
|
||||
|
||||
--echo # 2PC enabled, MyRocks durability enabled
|
||||
SET GLOBAL rocksdb_disable_2pc=0;
|
||||
SET GLOBAL rocksdb_enable_2pc=0;
|
||||
SET GLOBAL rocksdb_write_sync=1;
|
||||
|
||||
--echo ## 2PC + durability + single thread
|
||||
|
@ -28,7 +28,7 @@ select case when variable_value-@c > 0 and variable_value-@c < 10000 then 'true'
|
|||
|
||||
|
||||
--echo # 2PC enabled, MyRocks durability disabled
|
||||
SET GLOBAL rocksdb_disable_2pc=0;
|
||||
SET GLOBAL rocksdb_enable_2pc=0;
|
||||
SET GLOBAL rocksdb_write_sync=0;
|
||||
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
|
@ -41,7 +41,7 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
|
|||
|
||||
|
||||
--echo # 2PC disabled, MyRocks durability enabled
|
||||
SET GLOBAL rocksdb_disable_2pc=1;
|
||||
SET GLOBAL rocksdb_enable_2pc=1;
|
||||
SET GLOBAL rocksdb_write_sync=1;
|
||||
|
||||
select variable_value into @c from information_schema.global_status where variable_name='rocksdb_wal_group_syncs';
|
||||
|
@ -58,7 +58,7 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
|
|||
|
||||
|
||||
|
||||
SET GLOBAL rocksdb_disable_2pc=1;
|
||||
SET GLOBAL rocksdb_enable_2pc=1;
|
||||
SET GLOBAL rocksdb_write_sync=0;
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE mysqlslap;
|
||||
|
|
|
@ -89,22 +89,11 @@ while ($i <= $max) {
|
|||
--echo # crash_during_index_creation_partition
|
||||
flush logs;
|
||||
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
SET SESSION debug="+d,myrocks_simulate_index_create_rollback";
|
||||
|
||||
--echo # expected assertion failure from sql layer here for alter rollback
|
||||
call mtr.add_suppression("Assertion `0' failed.");
|
||||
call mtr.add_suppression("Attempting backtrace. You can use the following information to find out");
|
||||
|
||||
--error 2013
|
||||
|
||||
--error 1105
|
||||
ALTER TABLE t1 ADD INDEX kij(i,j), ALGORITHM=INPLACE;
|
||||
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
SET SESSION debug="-d,myrocks_simulate_index_create_rollback";
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
# here, the index numbers should be higher because previously 4 index numbers
|
||||
|
|
|
@ -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 count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||
|
||||
select VALUE into @keysIn from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
|
||||
|
||||
CREATE TABLE t1 (i1 INT, i2 INT, PRIMARY KEY (i1)) ENGINE = ROCKSDB;
|
||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
||||
|
||||
|
@ -21,6 +23,10 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
|||
select * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||
select count(*) from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO;
|
||||
|
||||
set global rocksdb_force_flush_memtable_now = true;
|
||||
set global rocksdb_compact_cf='default';
|
||||
select case when VALUE-@keysIn >= 3 then 'true' else 'false' end from INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS where CF_NAME = 'default' and LEVEL = 'Sum' and TYPE = 'KeyIn';
|
||||
|
||||
CREATE INDEX tindex1 on t1 (i1);
|
||||
--let $start_max_index_id = query_get_value(SELECT * from INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO where type = 'MAX_INDEX_ID', VALUE, 1)
|
||||
|
||||
|
|
|
@ -3,6 +3,5 @@
|
|||
let $skip_unique_check = 0;
|
||||
--source loaddata.inc
|
||||
let $skip_unique_check = 1;
|
||||
set session rocksdb_skip_unique_check=1;
|
||||
set session unique_checks=0;
|
||||
--source loaddata.inc
|
||||
|
||||
|
|
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 #
|
||||
CREATE TABLE t1 (id int primary key, value int) engine=RocksDB;
|
||||
SET rocksdb_skip_unique_check=1;
|
||||
SET unique_checks=0;
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(1, 3);
|
||||
|
@ -1779,7 +1779,7 @@ REPLACE INTO t1 VALUES(4, 4);
|
|||
INSERT INTO t1 VALUES(5, 5) ON DUPLICATE KEY UPDATE value=value+1;
|
||||
TRUNCATE TABLE t1;
|
||||
SET @save_rocksdb_bulk_load_size= @@rocksdb_bulk_load_size;
|
||||
SET rocksdb_skip_unique_check=0;
|
||||
SET unique_checks=1;
|
||||
SET rocksdb_commit_in_the_middle=1;
|
||||
SET rocksdb_bulk_load_size=10;
|
||||
BEGIN;
|
||||
|
|
|
@ -5,4 +5,4 @@ binlog_format=row
|
|||
[mysqld.2]
|
||||
binlog_format=row
|
||||
slave_parallel_workers=1
|
||||
rocksdb_rpl_skip_tx_api=ON
|
||||
rpl_skip_tx_api=ON
|
||||
|
|
|
@ -17,7 +17,7 @@ while ($aa < 1000) {
|
|||
--enable_query_log
|
||||
|
||||
connection slave;
|
||||
show variables like 'rocksdb_rpl_skip_tx_api';
|
||||
show variables like 'rpl_skip_tx_api';
|
||||
--source include/start_slave.inc
|
||||
|
||||
--let $it=0
|
||||
|
|
|
@ -31,3 +31,21 @@ INSERT INTO t2 VALUES (1,1);
|
|||
--error ER_DUP_ENTRY
|
||||
INSERT INTO t2 VALUES (2,1);
|
||||
DROP TABLE t2;
|
||||
|
||||
--echo #
|
||||
--echo # Issue #491 (https://github.com/facebook/mysql-5.6/issues/491)
|
||||
--echo #
|
||||
CREATE TABLE t (a BLOB, PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
|
||||
INSERT INTO t VALUES('a');
|
||||
CHECK TABLE t EXTENDED;
|
||||
DROP TABLE t;
|
||||
|
||||
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a), UNIQUE KEY (a(1))) engine=rocksdb;
|
||||
INSERT INTO t VALUES('a');
|
||||
CHECK TABLE t EXTENDED;
|
||||
DROP TABLE t;
|
||||
|
||||
CREATE TABLE t (a VARCHAR(255), PRIMARY KEY(a(2)), UNIQUE KEY (a(1))) engine=rocksdb;
|
||||
INSERT INTO t VALUES('a');
|
||||
CHECK TABLE t EXTENDED;
|
||||
DROP TABLE t;
|
||||
|
|
|
@ -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> \
|
||||
$COPY_LOG | xbstream -x \
|
||||
--directory=$backup_dir"
|
||||
elif [ "$STREAM_TYPE" == "xbstream_socket" ]; then
|
||||
BACKUP_CMD="$MYSQL_MYROCKS_HOTBACKUP --user='root' --socket=${MASTER_MYSOCK} \
|
||||
--stream=xbstream --checkpoint_dir=$checkpoint_dir 2> \
|
||||
$COPY_LOG | xbstream -x \
|
||||
--directory=$backup_dir"
|
||||
else
|
||||
BACKUP_CMD="$MYSQL_MYROCKS_HOTBACKUP --user='root' --stream=wdt \
|
||||
--port=${MASTER_MYPORT} --destination=localhost --backup_dir=$backup_dir \
|
||||
|
|
|
@ -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;
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
create table t1 (a int primary key, b int, c varchar(255)) engine=rocksdb;
|
||||
'con1'
|
||||
SET SESSION debug="d,crash_commit_after_log";
|
||||
|
@ -7,11 +7,11 @@ SET DEBUG_SYNC='rocksdb.prepared SIGNAL parked WAIT_FOR go';
|
|||
insert into t1 values (1, 1, "iamtheogthealphaandomega");;
|
||||
'con2'
|
||||
insert into t1 values (2, 1, "i_am_just_here_to_trigger_a_flush");
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_WRITE_SYNC = OFF;
|
||||
SET GLOBAL SYNC_BINLOG = 0;
|
||||
SET DEBUG_SYNC='now WAIT_FOR parked';
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_WRITE_SYNC = ON;
|
||||
SET GLOBAL SYNC_BINLOG = 1;
|
||||
insert into t1 values (1000000, 1, "i_am_just_here_to_trigger_a_flush");
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
DROP TABLE IF EXISTS t1;
|
||||
create table t1 (a int primary key, msg varchar(255)) engine=rocksdb;
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
SET SESSION debug="d,crash_commit_after_prepare";
|
||||
insert into t1 values (1, 'dogz');
|
||||
select * from t1;
|
||||
a msg
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
SET SESSION debug="d,crash_commit_after_log";
|
||||
insert into t1 values (2, 'catz'), (3, 'men');
|
||||
select * from t1;
|
||||
a msg
|
||||
2 catz
|
||||
3 men
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
SET SESSION debug="d,crash_commit_after";
|
||||
insert into t1 values (4, 'cars'), (5, 'foo');
|
||||
select * from t1;
|
||||
|
@ -21,7 +21,7 @@ a msg
|
|||
3 men
|
||||
4 cars
|
||||
5 foo
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||
SET SESSION debug="d,crash_commit_after_log";
|
||||
insert into t1 values (6, 'shipz'), (7, 'tankz');
|
||||
select * from t1;
|
||||
|
@ -30,7 +30,7 @@ a msg
|
|||
3 men
|
||||
4 cars
|
||||
5 foo
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||
SET SESSION debug="d,crash_commit_after";
|
||||
insert into t1 values (8, 'space'), (9, 'time');
|
||||
select * from t1;
|
||||
|
|
|
@ -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;
|
||||
--enable_warnings
|
||||
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
create table t1 (a int primary key, b int, c varchar(255)) engine=rocksdb;
|
||||
|
||||
connect (con1, localhost, root,,);
|
||||
|
@ -35,7 +35,7 @@ insert into t1 values (2, 1, "i_am_just_here_to_trigger_a_flush");
|
|||
|
||||
# Disable 2PC and syncing for faster inserting of dummy rows
|
||||
# These rows only purpose is to rotate the binlog
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_WRITE_SYNC = OFF;
|
||||
SET GLOBAL SYNC_BINLOG = 0;
|
||||
|
||||
|
@ -50,7 +50,7 @@ while ($pk < 1000000) {
|
|||
|
||||
# re-enable 2PC an syncing then write to trigger a flush
|
||||
# before we trigger the crash to simulate full-durability
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_WRITE_SYNC = ON;
|
||||
SET GLOBAL SYNC_BINLOG = 1;
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
[mysqld.1]
|
||||
log_slave_updates
|
||||
rocksdb_enable_2pc=OFF
|
||||
|
||||
[mysqld.2]
|
||||
relay_log_recovery=1
|
||||
relay_log_info_repository=TABLE
|
||||
log_slave_updates
|
||||
rocksdb_enable_2pc=OFF
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
log_slave_updates
|
||||
gtid_mode=ON
|
||||
enforce_gtid_consistency=ON
|
||||
rocksdb_enable_2pc=OFF
|
||||
|
||||
[mysqld.2]
|
||||
sync_relay_log_info=100
|
||||
|
@ -12,3 +13,4 @@ relay_log_info_repository=FILE
|
|||
log_slave_updates
|
||||
gtid_mode=ON
|
||||
enforce_gtid_consistency=ON
|
||||
rocksdb_enable_2pc=OFF
|
||||
|
|
|
@ -8,7 +8,7 @@ DROP TABLE IF EXISTS t1;
|
|||
|
||||
create table t1 (a int primary key, msg varchar(255)) engine=rocksdb;
|
||||
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
SET SESSION debug="d,crash_commit_after_prepare";
|
||||
--error 0,2013
|
||||
|
@ -17,7 +17,7 @@ insert into t1 values (1, 'dogz');
|
|||
--source include/wait_until_connected_again.inc
|
||||
select * from t1;
|
||||
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
SET SESSION debug="d,crash_commit_after_log";
|
||||
--error 0,2013
|
||||
|
@ -26,7 +26,7 @@ insert into t1 values (2, 'catz'), (3, 'men');
|
|||
--source include/wait_until_connected_again.inc
|
||||
select * from t1;
|
||||
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = OFF;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = ON;
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
SET SESSION debug="d,crash_commit_after";
|
||||
--error 0,2013
|
||||
|
@ -35,7 +35,7 @@ insert into t1 values (4, 'cars'), (5, 'foo');
|
|||
--source include/wait_until_connected_again.inc
|
||||
select * from t1;
|
||||
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
SET SESSION debug="d,crash_commit_after_log";
|
||||
--error 0,2013
|
||||
|
@ -44,7 +44,7 @@ insert into t1 values (6, 'shipz'), (7, 'tankz');
|
|||
--source include/wait_until_connected_again.inc
|
||||
select * from t1;
|
||||
|
||||
SET GLOBAL ROCKSDB_DISABLE_2PC = ON;
|
||||
SET GLOBAL ROCKSDB_ENABLE_2PC = OFF;
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
SET SESSION debug="d,crash_commit_after";
|
||||
--error 0,2013
|
||||
|
|
|
@ -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
|
||||
left join t1 on variable_name=test_name where test_name is null ORDER BY variable_name;
|
||||
There should be *no* variables listed below:
|
||||
ROCKSDB_ENABLE_2PC
|
||||
ROCKSDB_ENABLE_2PC
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
|
|
@ -6,70 +6,70 @@ INSERT INTO valid_values VALUES('off');
|
|||
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
||||
INSERT INTO invalid_values VALUES('\'aaa\'');
|
||||
INSERT INTO invalid_values VALUES('\'bbb\'');
|
||||
SET @start_global_value = @@global.ROCKSDB_DISABLE_2PC;
|
||||
SET @start_global_value = @@global.ROCKSDB_ENABLE_2PC;
|
||||
SELECT @start_global_value;
|
||||
@start_global_value
|
||||
1
|
||||
'# Setting to valid values in global scope#'
|
||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 1"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = 1;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 1"
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = 1;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Setting the global scope variable back to default"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 0"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = 0;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 0"
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = 0;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
0
|
||||
"Setting the global scope variable back to default"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to on"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = on;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to on"
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = on;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Setting the global scope variable back to default"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to off"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = off;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to off"
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = off;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
0
|
||||
"Setting the global scope variable back to default"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Trying to set variable @@session.ROCKSDB_DISABLE_2PC to 444. It should fail because it is not session."
|
||||
SET @@session.ROCKSDB_DISABLE_2PC = 444;
|
||||
ERROR HY000: Variable 'rocksdb_disable_2pc' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
"Trying to set variable @@session.ROCKSDB_ENABLE_2PC to 444. It should fail because it is not session."
|
||||
SET @@session.ROCKSDB_ENABLE_2PC = 444;
|
||||
ERROR HY000: Variable 'rocksdb_enable_2pc' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
'# Testing with invalid values in global scope #'
|
||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 'aaa'"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = 'aaa';
|
||||
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 'aaa'"
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = 'aaa';
|
||||
Got one of the listed errors
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
"Trying to set variable @@global.ROCKSDB_DISABLE_2PC to 'bbb'"
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = 'bbb';
|
||||
"Trying to set variable @@global.ROCKSDB_ENABLE_2PC to 'bbb'"
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = 'bbb';
|
||||
Got one of the listed errors
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
SET @@global.ROCKSDB_DISABLE_2PC = @start_global_value;
|
||||
SELECT @@global.ROCKSDB_DISABLE_2PC;
|
||||
@@global.ROCKSDB_DISABLE_2PC
|
||||
SET @@global.ROCKSDB_ENABLE_2PC = @start_global_value;
|
||||
SELECT @@global.ROCKSDB_ENABLE_2PC;
|
||||
@@global.ROCKSDB_ENABLE_2PC
|
||||
1
|
||||
DROP TABLE valid_values;
|
||||
DROP TABLE invalid_values;
|
||||
|
|
|
@ -1,7 +1,46 @@
|
|||
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
|
||||
INSERT INTO valid_values VALUES(1);
|
||||
INSERT INTO valid_values VALUES(64);
|
||||
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
||||
INSERT INTO invalid_values VALUES('\'abc\'');
|
||||
SET @start_global_value = @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
SELECT @start_global_value;
|
||||
@start_global_value
|
||||
1
|
||||
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 444. It should fail because it is readonly."
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 444;
|
||||
ERROR HY000: Variable 'rocksdb_max_background_compactions' is a read only variable
|
||||
'# Setting to valid values in global scope#'
|
||||
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 1"
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 1;
|
||||
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
1
|
||||
"Setting the global scope variable back to default"
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
1
|
||||
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 64"
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 64;
|
||||
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
64
|
||||
"Setting the global scope variable back to default"
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = DEFAULT;
|
||||
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
1
|
||||
"Trying to set variable @@session.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 444. It should fail because it is not session."
|
||||
SET @@session.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 444;
|
||||
ERROR HY000: Variable 'rocksdb_max_background_compactions' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
'# Testing with invalid values in global scope #'
|
||||
"Trying to set variable @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS to 'abc'"
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = 'abc';
|
||||
Got one of the listed errors
|
||||
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
1
|
||||
SET @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS = @start_global_value;
|
||||
SELECT @@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS;
|
||||
@@global.ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
1
|
||||
DROP TABLE valid_values;
|
||||
DROP TABLE invalid_values;
|
||||
|
|
|
@ -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('\'bbb\'');
|
||||
|
||||
--let $sys_var=ROCKSDB_DISABLE_2PC
|
||||
--let $sys_var=ROCKSDB_ENABLE_2PC
|
||||
--let $read_only=0
|
||||
--let $session=0
|
||||
--let $sticky=1
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
--source include/have_rocksdb.inc
|
||||
|
||||
CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam;
|
||||
INSERT INTO valid_values VALUES(1);
|
||||
INSERT INTO valid_values VALUES(64);
|
||||
|
||||
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
||||
INSERT INTO invalid_values VALUES('\'abc\'');
|
||||
|
||||
--let $sys_var=ROCKSDB_MAX_BACKGROUND_COMPACTIONS
|
||||
--let $read_only=1
|
||||
--let $read_only=0
|
||||
--let $session=0
|
||||
--source suite/sys_vars/inc/rocksdb_sys_var.inc
|
||||
|
||||
DROP TABLE valid_values;
|
||||
DROP TABLE invalid_values;
|
||||
|
|
|
@ -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;
|
||||
INSERT INTO valid_values VALUES(1);
|
||||
INSERT INTO valid_values VALUES(0);
|
||||
INSERT INTO valid_values VALUES('on');
|
||||
INSERT INTO valid_values VALUES('off');
|
||||
INSERT INTO valid_values VALUES(1024);
|
||||
|
||||
CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam;
|
||||
INSERT INTO invalid_values VALUES('\'aaa\'');
|
||||
|
||||
--let $sys_var=ROCKSDB_RPL_SKIP_TX_API
|
||||
--let $read_only=0
|
||||
--let $sys_var=ROCKSDB_PERSISTENT_CACHE_SIZE
|
||||
--let $read_only=1
|
||||
--let $session=0
|
||||
--source suite/sys_vars/inc/rocksdb_sys_var.inc
|
||||
|
|
@ -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);
|
||||
my_bool rocksdb_compaction_sequential_deletes_count_sd = false;
|
||||
|
||||
Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(
|
||||
Rdb_ddl_manager* const ddl_manager,
|
||||
const Rdb_compact_params ¶ms,
|
||||
const uint32_t &cf_id,
|
||||
const uint8_t &table_stats_sampling_pct
|
||||
) :
|
||||
m_cf_id(cf_id),
|
||||
m_ddl_manager(ddl_manager),
|
||||
m_last_stats(nullptr),
|
||||
m_rows(0l), m_window_pos(0l), m_deleted_rows(0l), m_max_deleted_rows(0l),
|
||||
m_file_size(0), m_params(params),
|
||||
m_table_stats_sampling_pct(table_stats_sampling_pct),
|
||||
m_seed(time(nullptr)),
|
||||
m_card_adj_extra(1.)
|
||||
{
|
||||
Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
|
||||
const Rdb_compact_params ¶ms,
|
||||
const uint32_t &cf_id,
|
||||
const uint8_t &table_stats_sampling_pct)
|
||||
: m_cf_id(cf_id), m_ddl_manager(ddl_manager), m_last_stats(nullptr),
|
||||
m_rows(0l), m_window_pos(0l), m_deleted_rows(0l), m_max_deleted_rows(0l),
|
||||
m_file_size(0), m_params(params),
|
||||
m_table_stats_sampling_pct(table_stats_sampling_pct),
|
||||
m_seed(time(nullptr)), m_card_adj_extra(1.) {
|
||||
DBUG_ASSERT(ddl_manager != nullptr);
|
||||
|
||||
// We need to adjust the index cardinality numbers based on the sampling
|
||||
|
@ -71,12 +65,11 @@ Rdb_tbl_prop_coll::Rdb_tbl_prop_coll(
|
|||
/*
|
||||
This function is called by RocksDB for every key in the SST file
|
||||
*/
|
||||
rocksdb::Status
|
||||
Rdb_tbl_prop_coll::AddUserKey(
|
||||
const rocksdb::Slice& key, const rocksdb::Slice& value,
|
||||
rocksdb::EntryType type, rocksdb::SequenceNumber seq,
|
||||
uint64_t file_size
|
||||
) {
|
||||
rocksdb::Status Rdb_tbl_prop_coll::AddUserKey(const rocksdb::Slice &key,
|
||||
const rocksdb::Slice &value,
|
||||
rocksdb::EntryType type,
|
||||
rocksdb::SequenceNumber seq,
|
||||
uint64_t file_size) {
|
||||
if (key.size() >= 4) {
|
||||
AdjustDeletedRows(type);
|
||||
|
||||
|
@ -88,10 +81,8 @@ Rdb_tbl_prop_coll::AddUserKey(
|
|||
return rocksdb::Status::OK();
|
||||
}
|
||||
|
||||
void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type)
|
||||
{
|
||||
if (m_params.m_window > 0)
|
||||
{
|
||||
void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type) {
|
||||
if (m_params.m_window > 0) {
|
||||
// record the "is deleted" flag into the sliding window
|
||||
// the sliding window is implemented as a circular buffer
|
||||
// in m_deleted_rows_window vector
|
||||
|
@ -99,42 +90,33 @@ void Rdb_tbl_prop_coll::AdjustDeletedRows(rocksdb::EntryType type)
|
|||
// m_rows % m_deleted_rows_window.size()
|
||||
// m_deleted_rows is the current number of 1's in the vector
|
||||
// --update the counter for the element which will be overridden
|
||||
const bool is_delete= (type == rocksdb::kEntryDelete ||
|
||||
(type == rocksdb::kEntrySingleDelete &&
|
||||
rocksdb_compaction_sequential_deletes_count_sd));
|
||||
const bool is_delete = (type == rocksdb::kEntryDelete ||
|
||||
(type == rocksdb::kEntrySingleDelete &&
|
||||
rocksdb_compaction_sequential_deletes_count_sd));
|
||||
|
||||
// Only make changes if the value at the current position needs to change
|
||||
if (is_delete != m_deleted_rows_window[m_window_pos])
|
||||
{
|
||||
if (is_delete != m_deleted_rows_window[m_window_pos]) {
|
||||
// Set or clear the flag at the current position as appropriate
|
||||
m_deleted_rows_window[m_window_pos]= is_delete;
|
||||
if (!is_delete)
|
||||
{
|
||||
m_deleted_rows_window[m_window_pos] = is_delete;
|
||||
if (!is_delete) {
|
||||
m_deleted_rows--;
|
||||
}
|
||||
else if (++m_deleted_rows > m_max_deleted_rows)
|
||||
{
|
||||
} else if (++m_deleted_rows > m_max_deleted_rows) {
|
||||
m_max_deleted_rows = m_deleted_rows;
|
||||
}
|
||||
}
|
||||
|
||||
if (++m_window_pos == m_params.m_window)
|
||||
{
|
||||
if (++m_window_pos == m_params.m_window) {
|
||||
m_window_pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
|
||||
const rocksdb::Slice& key)
|
||||
{
|
||||
GL_INDEX_ID gl_index_id = {
|
||||
.cf_id = m_cf_id,
|
||||
.index_id = rdb_netbuf_to_uint32(reinterpret_cast<const uchar*>(key.data()))
|
||||
};
|
||||
Rdb_index_stats *Rdb_tbl_prop_coll::AccessStats(const rocksdb::Slice &key) {
|
||||
GL_INDEX_ID gl_index_id = {.cf_id = m_cf_id,
|
||||
.index_id = rdb_netbuf_to_uint32(
|
||||
reinterpret_cast<const uchar *>(key.data()))};
|
||||
|
||||
if (m_last_stats == nullptr || m_last_stats->m_gl_index_id != gl_index_id)
|
||||
{
|
||||
if (m_last_stats == nullptr || m_last_stats->m_gl_index_id != gl_index_id) {
|
||||
m_keydef = nullptr;
|
||||
|
||||
// starting a new table
|
||||
|
@ -142,8 +124,7 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
|
|||
m_stats.emplace_back(gl_index_id);
|
||||
m_last_stats = &m_stats.back();
|
||||
|
||||
if (m_ddl_manager)
|
||||
{
|
||||
if (m_ddl_manager) {
|
||||
// safe_find() returns a std::shared_ptr<Rdb_key_def> with the count
|
||||
// incremented (so it can't be deleted out from under us) and with
|
||||
// the mutex locked (if setup has not occurred yet). We must make
|
||||
|
@ -152,8 +133,7 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
|
|||
// when we are switching to a new Rdb_key_def and when this object
|
||||
// is destructed.
|
||||
m_keydef = m_ddl_manager->safe_find(gl_index_id);
|
||||
if (m_keydef != nullptr)
|
||||
{
|
||||
if (m_keydef != nullptr) {
|
||||
// resize the array to the number of columns.
|
||||
// It will be initialized with zeroes
|
||||
m_last_stats->m_distinct_keys_per_prefix.resize(
|
||||
|
@ -167,13 +147,13 @@ Rdb_index_stats* Rdb_tbl_prop_coll::AccessStats(
|
|||
return m_last_stats;
|
||||
}
|
||||
|
||||
void Rdb_tbl_prop_coll::CollectStatsForRow(
|
||||
const rocksdb::Slice& key, const rocksdb::Slice& value,
|
||||
const rocksdb::EntryType &type, const uint64_t &file_size)
|
||||
{
|
||||
void Rdb_tbl_prop_coll::CollectStatsForRow(const rocksdb::Slice &key,
|
||||
const rocksdb::Slice &value,
|
||||
const rocksdb::EntryType &type,
|
||||
const uint64_t &file_size) {
|
||||
const auto stats = AccessStats(key);
|
||||
|
||||
stats->m_data_size += key.size()+value.size();
|
||||
stats->m_data_size += key.size() + value.size();
|
||||
|
||||
// Incrementing per-index entry-type statistics
|
||||
switch (type) {
|
||||
|
@ -195,7 +175,8 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
|
|||
default:
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("RocksDB: Unexpected entry type found: %u. "
|
||||
"This should not happen so aborting the system.", type);
|
||||
"This should not happen so aborting the system.",
|
||||
type);
|
||||
abort_with_stack_traces();
|
||||
break;
|
||||
}
|
||||
|
@ -203,23 +184,19 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
|
|||
stats->m_actual_disk_size += file_size - m_file_size;
|
||||
m_file_size = file_size;
|
||||
|
||||
if (m_keydef != nullptr && ShouldCollectStats())
|
||||
{
|
||||
if (m_keydef != nullptr && ShouldCollectStats()) {
|
||||
std::size_t column = 0;
|
||||
bool new_key = true;
|
||||
|
||||
if (!m_last_key.empty())
|
||||
{
|
||||
if (!m_last_key.empty()) {
|
||||
rocksdb::Slice last(m_last_key.data(), m_last_key.size());
|
||||
new_key = (m_keydef->compare_keys(&last, &key, &column) == 0);
|
||||
}
|
||||
|
||||
if (new_key)
|
||||
{
|
||||
if (new_key) {
|
||||
DBUG_ASSERT(column <= stats->m_distinct_keys_per_prefix.size());
|
||||
|
||||
for (auto i = column; i < stats->m_distinct_keys_per_prefix.size(); i++)
|
||||
{
|
||||
for (auto i = column; i < stats->m_distinct_keys_per_prefix.size(); i++) {
|
||||
stats->m_distinct_keys_per_prefix[i]++;
|
||||
}
|
||||
|
||||
|
@ -228,23 +205,20 @@ void Rdb_tbl_prop_coll::CollectStatsForRow(
|
|||
// if one of the first n-1 columns is different
|
||||
// If the n-1 prefix is the same, no sense in storing
|
||||
// the new key
|
||||
if (column < stats->m_distinct_keys_per_prefix.size())
|
||||
{
|
||||
if (column < stats->m_distinct_keys_per_prefix.size()) {
|
||||
m_last_key.assign(key.data(), key.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* Rdb_tbl_prop_coll::INDEXSTATS_KEY = "__indexstats__";
|
||||
const char *Rdb_tbl_prop_coll::INDEXSTATS_KEY = "__indexstats__";
|
||||
|
||||
/*
|
||||
This function is called by RocksDB to compute properties to store in sst file
|
||||
*/
|
||||
rocksdb::Status
|
||||
Rdb_tbl_prop_coll::Finish(
|
||||
rocksdb::UserCollectedProperties* const properties
|
||||
) {
|
||||
Rdb_tbl_prop_coll::Finish(rocksdb::UserCollectedProperties *const properties) {
|
||||
uint64_t num_sst_entry_put = 0;
|
||||
uint64_t num_sst_entry_delete = 0;
|
||||
uint64_t num_sst_entry_singledelete = 0;
|
||||
|
@ -253,8 +227,7 @@ Rdb_tbl_prop_coll::Finish(
|
|||
|
||||
DBUG_ASSERT(properties != nullptr);
|
||||
|
||||
for (auto it = m_stats.begin(); it != m_stats.end(); it++)
|
||||
{
|
||||
for (auto it = m_stats.begin(); it != m_stats.end(); it++) {
|
||||
num_sst_entry_put += it->m_rows;
|
||||
num_sst_entry_delete += it->m_entry_deletes;
|
||||
num_sst_entry_singledelete += it->m_entry_single_deletes;
|
||||
|
@ -262,42 +235,35 @@ Rdb_tbl_prop_coll::Finish(
|
|||
num_sst_entry_other += it->m_entry_others;
|
||||
}
|
||||
|
||||
if (num_sst_entry_put > 0)
|
||||
{
|
||||
if (num_sst_entry_put > 0) {
|
||||
rocksdb_num_sst_entry_put += num_sst_entry_put;
|
||||
}
|
||||
|
||||
if (num_sst_entry_delete > 0)
|
||||
{
|
||||
if (num_sst_entry_delete > 0) {
|
||||
rocksdb_num_sst_entry_delete += num_sst_entry_delete;
|
||||
}
|
||||
|
||||
if (num_sst_entry_singledelete > 0)
|
||||
{
|
||||
if (num_sst_entry_singledelete > 0) {
|
||||
rocksdb_num_sst_entry_singledelete += num_sst_entry_singledelete;
|
||||
}
|
||||
|
||||
if (num_sst_entry_merge > 0)
|
||||
{
|
||||
if (num_sst_entry_merge > 0) {
|
||||
rocksdb_num_sst_entry_merge += num_sst_entry_merge;
|
||||
}
|
||||
|
||||
if (num_sst_entry_other > 0)
|
||||
{
|
||||
if (num_sst_entry_other > 0) {
|
||||
rocksdb_num_sst_entry_other += num_sst_entry_other;
|
||||
}
|
||||
|
||||
properties->insert({INDEXSTATS_KEY,
|
||||
Rdb_index_stats::materialize(m_stats, m_card_adj_extra)});
|
||||
Rdb_index_stats::materialize(m_stats, m_card_adj_extra)});
|
||||
return rocksdb::Status::OK();
|
||||
}
|
||||
|
||||
bool Rdb_tbl_prop_coll::NeedCompact() const {
|
||||
return
|
||||
m_params.m_deletes &&
|
||||
(m_params.m_window > 0) &&
|
||||
(m_file_size > m_params.m_file_size) &&
|
||||
(m_max_deleted_rows > m_params.m_deletes);
|
||||
return m_params.m_deletes && (m_params.m_window > 0) &&
|
||||
(m_file_size > m_params.m_file_size) &&
|
||||
(m_max_deleted_rows > m_params.m_deletes);
|
||||
}
|
||||
|
||||
bool Rdb_tbl_prop_coll::ShouldCollectStats() {
|
||||
|
@ -307,9 +273,9 @@ bool Rdb_tbl_prop_coll::ShouldCollectStats() {
|
|||
return true;
|
||||
}
|
||||
|
||||
const int val = rand_r(&m_seed) %
|
||||
(RDB_TBL_STATS_SAMPLE_PCT_MAX - RDB_TBL_STATS_SAMPLE_PCT_MIN + 1) +
|
||||
RDB_TBL_STATS_SAMPLE_PCT_MIN;
|
||||
const int val = rand_r(&m_seed) % (RDB_TBL_STATS_SAMPLE_PCT_MAX -
|
||||
RDB_TBL_STATS_SAMPLE_PCT_MIN + 1) +
|
||||
RDB_TBL_STATS_SAMPLE_PCT_MIN;
|
||||
|
||||
DBUG_ASSERT(val >= RDB_TBL_STATS_SAMPLE_PCT_MIN);
|
||||
DBUG_ASSERT(val <= RDB_TBL_STATS_SAMPLE_PCT_MAX);
|
||||
|
@ -337,14 +303,11 @@ Rdb_tbl_prop_coll::GetReadableProperties() const {
|
|||
}
|
||||
s.append(GetReadableStats(it));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return rocksdb::UserCollectedProperties{{INDEXSTATS_KEY, s}};
|
||||
}
|
||||
|
||||
std::string
|
||||
Rdb_tbl_prop_coll::GetReadableStats(
|
||||
const Rdb_index_stats& it
|
||||
) {
|
||||
std::string Rdb_tbl_prop_coll::GetReadableStats(const Rdb_index_stats &it) {
|
||||
std::string s;
|
||||
s.append("(");
|
||||
s.append(std::to_string(it.m_gl_index_id.cf_id));
|
||||
|
@ -380,28 +343,24 @@ Rdb_tbl_prop_coll::GetReadableStats(
|
|||
*/
|
||||
|
||||
void Rdb_tbl_prop_coll::read_stats_from_tbl_props(
|
||||
const std::shared_ptr<const rocksdb::TableProperties>& table_props,
|
||||
std::vector<Rdb_index_stats>* const out_stats_vector)
|
||||
{
|
||||
const std::shared_ptr<const rocksdb::TableProperties> &table_props,
|
||||
std::vector<Rdb_index_stats> *const out_stats_vector) {
|
||||
DBUG_ASSERT(out_stats_vector != nullptr);
|
||||
const auto& user_properties = table_props->user_collected_properties;
|
||||
const auto &user_properties = table_props->user_collected_properties;
|
||||
const auto it2 = user_properties.find(std::string(INDEXSTATS_KEY));
|
||||
if (it2 != user_properties.end())
|
||||
{
|
||||
auto result __attribute__((__unused__)) =
|
||||
if (it2 != user_properties.end()) {
|
||||
auto result MY_ATTRIBUTE((__unused__)) =
|
||||
Rdb_index_stats::unmaterialize(it2->second, out_stats_vector);
|
||||
DBUG_ASSERT(result == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Serializes an array of Rdb_index_stats into a network string.
|
||||
*/
|
||||
std::string Rdb_index_stats::materialize(
|
||||
const std::vector<Rdb_index_stats>& stats,
|
||||
const float card_adj_extra)
|
||||
{
|
||||
std::string
|
||||
Rdb_index_stats::materialize(const std::vector<Rdb_index_stats> &stats,
|
||||
const float card_adj_extra) {
|
||||
String ret;
|
||||
rdb_netstr_append_uint16(&ret, INDEX_STATS_VERSION_ENTRY_TYPES);
|
||||
for (const auto &i : stats) {
|
||||
|
@ -422,105 +381,92 @@ std::string Rdb_index_stats::materialize(
|
|||
}
|
||||
}
|
||||
|
||||
return std::string((char*) ret.ptr(), ret.length());
|
||||
return std::string((char *)ret.ptr(), ret.length());
|
||||
}
|
||||
|
||||
/**
|
||||
@brief
|
||||
Reads an array of Rdb_index_stats from a string.
|
||||
@return 1 if it detects any inconsistency in the input
|
||||
@return 0 if completes successfully
|
||||
@return HA_EXIT_FAILURE if it detects any inconsistency in the input
|
||||
@return HA_EXIT_SUCCESS if completes successfully
|
||||
*/
|
||||
int Rdb_index_stats::unmaterialize(
|
||||
const std::string& s, std::vector<Rdb_index_stats>* const ret)
|
||||
{
|
||||
const uchar* p= rdb_std_str_to_uchar_ptr(s);
|
||||
const uchar* const p2= p + s.size();
|
||||
int Rdb_index_stats::unmaterialize(const std::string &s,
|
||||
std::vector<Rdb_index_stats> *const ret) {
|
||||
const uchar *p = rdb_std_str_to_uchar_ptr(s);
|
||||
const uchar *const p2 = p + s.size();
|
||||
|
||||
DBUG_ASSERT(ret != nullptr);
|
||||
|
||||
if (p+2 > p2)
|
||||
{
|
||||
return 1;
|
||||
if (p + 2 > p2) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const int version= rdb_netbuf_read_uint16(&p);
|
||||
const int version = rdb_netbuf_read_uint16(&p);
|
||||
Rdb_index_stats stats;
|
||||
// Make sure version is within supported range.
|
||||
if (version < INDEX_STATS_VERSION_INITIAL ||
|
||||
version > INDEX_STATS_VERSION_ENTRY_TYPES)
|
||||
{
|
||||
version > INDEX_STATS_VERSION_ENTRY_TYPES) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Index stats version %d was outside of supported range. "
|
||||
"This should not happen so aborting the system.", version);
|
||||
"This should not happen so aborting the system.",
|
||||
version);
|
||||
abort_with_stack_traces();
|
||||
}
|
||||
|
||||
size_t needed = sizeof(stats.m_gl_index_id.cf_id)+
|
||||
sizeof(stats.m_gl_index_id.index_id)+
|
||||
sizeof(stats.m_data_size)+
|
||||
sizeof(stats.m_rows)+
|
||||
sizeof(stats.m_actual_disk_size)+
|
||||
sizeof(uint64);
|
||||
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES)
|
||||
{
|
||||
needed += sizeof(stats.m_entry_deletes)+
|
||||
sizeof(stats.m_entry_single_deletes)+
|
||||
sizeof(stats.m_entry_merges)+
|
||||
sizeof(stats.m_entry_others);
|
||||
size_t needed = sizeof(stats.m_gl_index_id.cf_id) +
|
||||
sizeof(stats.m_gl_index_id.index_id) +
|
||||
sizeof(stats.m_data_size) + sizeof(stats.m_rows) +
|
||||
sizeof(stats.m_actual_disk_size) + sizeof(uint64);
|
||||
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES) {
|
||||
needed += sizeof(stats.m_entry_deletes) +
|
||||
sizeof(stats.m_entry_single_deletes) +
|
||||
sizeof(stats.m_entry_merges) + sizeof(stats.m_entry_others);
|
||||
}
|
||||
|
||||
while (p < p2)
|
||||
{
|
||||
if (p+needed > p2)
|
||||
{
|
||||
return 1;
|
||||
while (p < p2) {
|
||||
if (p + needed > p2) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
rdb_netbuf_read_gl_index(&p, &stats.m_gl_index_id);
|
||||
stats.m_data_size= rdb_netbuf_read_uint64(&p);
|
||||
stats.m_rows= rdb_netbuf_read_uint64(&p);
|
||||
stats.m_actual_disk_size= rdb_netbuf_read_uint64(&p);
|
||||
stats.m_data_size = rdb_netbuf_read_uint64(&p);
|
||||
stats.m_rows = rdb_netbuf_read_uint64(&p);
|
||||
stats.m_actual_disk_size = rdb_netbuf_read_uint64(&p);
|
||||
stats.m_distinct_keys_per_prefix.resize(rdb_netbuf_read_uint64(&p));
|
||||
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES)
|
||||
{
|
||||
stats.m_entry_deletes= rdb_netbuf_read_uint64(&p);
|
||||
stats.m_entry_single_deletes= rdb_netbuf_read_uint64(&p);
|
||||
stats.m_entry_merges= rdb_netbuf_read_uint64(&p);
|
||||
stats.m_entry_others= rdb_netbuf_read_uint64(&p);
|
||||
if (version >= INDEX_STATS_VERSION_ENTRY_TYPES) {
|
||||
stats.m_entry_deletes = rdb_netbuf_read_uint64(&p);
|
||||
stats.m_entry_single_deletes = rdb_netbuf_read_uint64(&p);
|
||||
stats.m_entry_merges = rdb_netbuf_read_uint64(&p);
|
||||
stats.m_entry_others = rdb_netbuf_read_uint64(&p);
|
||||
}
|
||||
if (p+stats.m_distinct_keys_per_prefix.size()
|
||||
*sizeof(stats.m_distinct_keys_per_prefix[0]) > p2)
|
||||
{
|
||||
return 1;
|
||||
if (p +
|
||||
stats.m_distinct_keys_per_prefix.size() *
|
||||
sizeof(stats.m_distinct_keys_per_prefix[0]) >
|
||||
p2) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
for (std::size_t i= 0; i < stats.m_distinct_keys_per_prefix.size(); i++)
|
||||
{
|
||||
stats.m_distinct_keys_per_prefix[i]= rdb_netbuf_read_uint64(&p);
|
||||
for (std::size_t i = 0; i < stats.m_distinct_keys_per_prefix.size(); i++) {
|
||||
stats.m_distinct_keys_per_prefix[i] = rdb_netbuf_read_uint64(&p);
|
||||
}
|
||||
ret->push_back(stats);
|
||||
}
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
Merges one Rdb_index_stats into another. Can be used to come up with the stats
|
||||
for the index based on stats for each sst
|
||||
*/
|
||||
void Rdb_index_stats::merge(
|
||||
const Rdb_index_stats& s, const bool &increment,
|
||||
const int64_t &estimated_data_len)
|
||||
{
|
||||
void Rdb_index_stats::merge(const Rdb_index_stats &s, const bool &increment,
|
||||
const int64_t &estimated_data_len) {
|
||||
std::size_t i;
|
||||
|
||||
DBUG_ASSERT(estimated_data_len >= 0);
|
||||
|
||||
m_gl_index_id = s.m_gl_index_id;
|
||||
if (m_distinct_keys_per_prefix.size() < s.m_distinct_keys_per_prefix.size())
|
||||
{
|
||||
if (m_distinct_keys_per_prefix.size() < s.m_distinct_keys_per_prefix.size()) {
|
||||
m_distinct_keys_per_prefix.resize(s.m_distinct_keys_per_prefix.size());
|
||||
}
|
||||
if (increment)
|
||||
{
|
||||
if (increment) {
|
||||
m_rows += s.m_rows;
|
||||
m_data_size += s.m_data_size;
|
||||
|
||||
|
@ -531,32 +477,28 @@ void Rdb_index_stats::merge(
|
|||
we make a reasoned estimate for the data_file_length for the
|
||||
index in the current SST.
|
||||
*/
|
||||
m_actual_disk_size += s.m_actual_disk_size ? s.m_actual_disk_size :
|
||||
estimated_data_len * s.m_rows;
|
||||
m_actual_disk_size += s.m_actual_disk_size ? s.m_actual_disk_size
|
||||
: estimated_data_len * s.m_rows;
|
||||
m_entry_deletes += s.m_entry_deletes;
|
||||
m_entry_single_deletes += s.m_entry_single_deletes;
|
||||
m_entry_merges += s.m_entry_merges;
|
||||
m_entry_others += s.m_entry_others;
|
||||
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++)
|
||||
{
|
||||
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++) {
|
||||
m_distinct_keys_per_prefix[i] += s.m_distinct_keys_per_prefix[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_rows -= s.m_rows;
|
||||
m_data_size -= s.m_data_size;
|
||||
m_actual_disk_size -= s.m_actual_disk_size ? s.m_actual_disk_size :
|
||||
estimated_data_len * s.m_rows;
|
||||
m_actual_disk_size -= s.m_actual_disk_size ? s.m_actual_disk_size
|
||||
: estimated_data_len * s.m_rows;
|
||||
m_entry_deletes -= s.m_entry_deletes;
|
||||
m_entry_single_deletes -= s.m_entry_single_deletes;
|
||||
m_entry_merges -= s.m_entry_merges;
|
||||
m_entry_others -= s.m_entry_others;
|
||||
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++)
|
||||
{
|
||||
for (i = 0; i < s.m_distinct_keys_per_prefix.size(); i++) {
|
||||
m_distinct_keys_per_prefix[i] -= s.m_distinct_keys_per_prefix[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -40,102 +40,87 @@ extern std::atomic<uint64_t> rocksdb_num_sst_entry_merge;
|
|||
extern std::atomic<uint64_t> rocksdb_num_sst_entry_other;
|
||||
extern my_bool rocksdb_compaction_sequential_deletes_count_sd;
|
||||
|
||||
|
||||
struct Rdb_compact_params
|
||||
{
|
||||
struct Rdb_compact_params {
|
||||
uint64_t m_deletes, m_window, m_file_size;
|
||||
};
|
||||
|
||||
|
||||
struct Rdb_index_stats
|
||||
{
|
||||
enum {
|
||||
INDEX_STATS_VERSION_INITIAL= 1,
|
||||
INDEX_STATS_VERSION_ENTRY_TYPES= 2,
|
||||
struct Rdb_index_stats {
|
||||
enum {
|
||||
INDEX_STATS_VERSION_INITIAL = 1,
|
||||
INDEX_STATS_VERSION_ENTRY_TYPES = 2,
|
||||
};
|
||||
GL_INDEX_ID m_gl_index_id;
|
||||
int64_t m_data_size, m_rows, m_actual_disk_size;
|
||||
int64_t m_entry_deletes, m_entry_single_deletes;
|
||||
int64_t m_entry_merges, m_entry_others;
|
||||
std::vector<int64_t> m_distinct_keys_per_prefix;
|
||||
std::string m_name; // name is not persisted
|
||||
std::string m_name; // name is not persisted
|
||||
|
||||
static std::string materialize(const std::vector<Rdb_index_stats>& stats,
|
||||
static std::string materialize(const std::vector<Rdb_index_stats> &stats,
|
||||
const float card_adj_extra);
|
||||
static int unmaterialize(const std::string& s,
|
||||
std::vector<Rdb_index_stats>* const ret);
|
||||
static int unmaterialize(const std::string &s,
|
||||
std::vector<Rdb_index_stats> *const ret);
|
||||
|
||||
Rdb_index_stats() : Rdb_index_stats({0, 0}) {}
|
||||
explicit Rdb_index_stats(GL_INDEX_ID gl_index_id) :
|
||||
m_gl_index_id(gl_index_id),
|
||||
m_data_size(0),
|
||||
m_rows(0),
|
||||
m_actual_disk_size(0),
|
||||
m_entry_deletes(0),
|
||||
m_entry_single_deletes(0),
|
||||
m_entry_merges(0),
|
||||
m_entry_others(0) {}
|
||||
explicit Rdb_index_stats(GL_INDEX_ID gl_index_id)
|
||||
: m_gl_index_id(gl_index_id), m_data_size(0), m_rows(0),
|
||||
m_actual_disk_size(0), m_entry_deletes(0), m_entry_single_deletes(0),
|
||||
m_entry_merges(0), m_entry_others(0) {}
|
||||
|
||||
void merge(const Rdb_index_stats& s, const bool &increment = true,
|
||||
void merge(const Rdb_index_stats &s, const bool &increment = true,
|
||||
const int64_t &estimated_data_len = 0);
|
||||
};
|
||||
|
||||
|
||||
class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
|
||||
{
|
||||
public:
|
||||
Rdb_tbl_prop_coll(
|
||||
Rdb_ddl_manager* const ddl_manager,
|
||||
const Rdb_compact_params ¶ms,
|
||||
const uint32_t &cf_id,
|
||||
const uint8_t &table_stats_sampling_pct
|
||||
);
|
||||
class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector {
|
||||
public:
|
||||
Rdb_tbl_prop_coll(Rdb_ddl_manager *const ddl_manager,
|
||||
const Rdb_compact_params ¶ms, const uint32_t &cf_id,
|
||||
const uint8_t &table_stats_sampling_pct);
|
||||
|
||||
/*
|
||||
Override parent class's virtual methods of interest.
|
||||
*/
|
||||
|
||||
virtual rocksdb::Status AddUserKey(
|
||||
const rocksdb::Slice& key, const rocksdb::Slice& value,
|
||||
rocksdb::EntryType type, rocksdb::SequenceNumber seq,
|
||||
uint64_t file_size);
|
||||
virtual rocksdb::Status AddUserKey(const rocksdb::Slice &key,
|
||||
const rocksdb::Slice &value,
|
||||
rocksdb::EntryType type,
|
||||
rocksdb::SequenceNumber seq,
|
||||
uint64_t file_size);
|
||||
|
||||
virtual rocksdb::Status Finish(rocksdb::UserCollectedProperties* properties) override;
|
||||
virtual rocksdb::Status
|
||||
Finish(rocksdb::UserCollectedProperties *properties) override;
|
||||
|
||||
virtual const char* Name() const override {
|
||||
return "Rdb_tbl_prop_coll";
|
||||
}
|
||||
virtual const char *Name() const override { return "Rdb_tbl_prop_coll"; }
|
||||
|
||||
rocksdb::UserCollectedProperties GetReadableProperties() const override;
|
||||
|
||||
bool NeedCompact() const override;
|
||||
|
||||
public:
|
||||
uint64_t GetMaxDeletedRows() const {
|
||||
return m_max_deleted_rows;
|
||||
}
|
||||
public:
|
||||
uint64_t GetMaxDeletedRows() const { return m_max_deleted_rows; }
|
||||
|
||||
static void read_stats_from_tbl_props(
|
||||
const std::shared_ptr<const rocksdb::TableProperties>& table_props,
|
||||
std::vector<Rdb_index_stats>* out_stats_vector);
|
||||
const std::shared_ptr<const rocksdb::TableProperties> &table_props,
|
||||
std::vector<Rdb_index_stats> *out_stats_vector);
|
||||
|
||||
private:
|
||||
static std::string GetReadableStats(const Rdb_index_stats& it);
|
||||
private:
|
||||
static std::string GetReadableStats(const Rdb_index_stats &it);
|
||||
|
||||
bool ShouldCollectStats();
|
||||
void CollectStatsForRow(const rocksdb::Slice& key,
|
||||
const rocksdb::Slice& value, const rocksdb::EntryType &type,
|
||||
const uint64_t &file_size);
|
||||
Rdb_index_stats* AccessStats(const rocksdb::Slice& key);
|
||||
void CollectStatsForRow(const rocksdb::Slice &key,
|
||||
const rocksdb::Slice &value,
|
||||
const rocksdb::EntryType &type,
|
||||
const uint64_t &file_size);
|
||||
Rdb_index_stats *AccessStats(const rocksdb::Slice &key);
|
||||
void AdjustDeletedRows(rocksdb::EntryType type);
|
||||
|
||||
private:
|
||||
private:
|
||||
uint32_t m_cf_id;
|
||||
std::shared_ptr<const Rdb_key_def> m_keydef;
|
||||
Rdb_ddl_manager* m_ddl_manager;
|
||||
Rdb_ddl_manager *m_ddl_manager;
|
||||
std::vector<Rdb_index_stats> m_stats;
|
||||
Rdb_index_stats* m_last_stats;
|
||||
static const char* INDEXSTATS_KEY;
|
||||
Rdb_index_stats *m_last_stats;
|
||||
static const char *INDEXSTATS_KEY;
|
||||
|
||||
// last added key
|
||||
std::string m_last_key;
|
||||
|
@ -150,34 +135,33 @@ class Rdb_tbl_prop_coll : public rocksdb::TablePropertiesCollector
|
|||
float m_card_adj_extra;
|
||||
};
|
||||
|
||||
|
||||
class Rdb_tbl_prop_coll_factory
|
||||
: public rocksdb::TablePropertiesCollectorFactory {
|
||||
public:
|
||||
Rdb_tbl_prop_coll_factory(const Rdb_tbl_prop_coll_factory&) = delete;
|
||||
Rdb_tbl_prop_coll_factory& operator=(const Rdb_tbl_prop_coll_factory&) = delete;
|
||||
public:
|
||||
Rdb_tbl_prop_coll_factory(const Rdb_tbl_prop_coll_factory &) = delete;
|
||||
Rdb_tbl_prop_coll_factory &
|
||||
operator=(const Rdb_tbl_prop_coll_factory &) = delete;
|
||||
|
||||
explicit Rdb_tbl_prop_coll_factory(Rdb_ddl_manager* ddl_manager)
|
||||
: m_ddl_manager(ddl_manager) {
|
||||
}
|
||||
explicit Rdb_tbl_prop_coll_factory(Rdb_ddl_manager *ddl_manager)
|
||||
: m_ddl_manager(ddl_manager) {}
|
||||
|
||||
/*
|
||||
Override parent class's virtual methods of interest.
|
||||
*/
|
||||
|
||||
virtual rocksdb::TablePropertiesCollector* CreateTablePropertiesCollector(
|
||||
virtual rocksdb::TablePropertiesCollector *CreateTablePropertiesCollector(
|
||||
rocksdb::TablePropertiesCollectorFactory::Context context) override {
|
||||
return new Rdb_tbl_prop_coll(
|
||||
m_ddl_manager, m_params, context.column_family_id,
|
||||
m_table_stats_sampling_pct);
|
||||
return new Rdb_tbl_prop_coll(m_ddl_manager, m_params,
|
||||
context.column_family_id,
|
||||
m_table_stats_sampling_pct);
|
||||
}
|
||||
|
||||
virtual const char* Name() const override {
|
||||
virtual const char *Name() const override {
|
||||
return "Rdb_tbl_prop_coll_factory";
|
||||
}
|
||||
|
||||
public:
|
||||
void SetCompactionParams(const Rdb_compact_params& params) {
|
||||
public:
|
||||
void SetCompactionParams(const Rdb_compact_params ¶ms) {
|
||||
m_params = params;
|
||||
}
|
||||
|
||||
|
@ -185,10 +169,10 @@ class Rdb_tbl_prop_coll_factory
|
|||
m_table_stats_sampling_pct = table_stats_sampling_pct;
|
||||
}
|
||||
|
||||
private:
|
||||
Rdb_ddl_manager* const m_ddl_manager;
|
||||
private:
|
||||
Rdb_ddl_manager *const m_ddl_manager;
|
||||
Rdb_compact_params m_params;
|
||||
uint8_t m_table_stats_sampling_pct;
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -27,97 +27,86 @@ namespace myrocks {
|
|||
("netstr") which stores data in Network Byte Order (Big Endian).
|
||||
*/
|
||||
|
||||
inline void rdb_netstr_append_uint64(my_core::String* const out_netstr,
|
||||
const uint64 &val)
|
||||
{
|
||||
inline void rdb_netstr_append_uint64(my_core::String *const out_netstr,
|
||||
const uint64 &val) {
|
||||
DBUG_ASSERT(out_netstr != nullptr);
|
||||
|
||||
// Convert from host machine byte order (usually Little Endian) to network
|
||||
// byte order (Big Endian).
|
||||
uint64 net_val= htobe64(val);
|
||||
out_netstr->append(reinterpret_cast<char*>(&net_val), sizeof(net_val));
|
||||
uint64 net_val = htobe64(val);
|
||||
out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
|
||||
}
|
||||
|
||||
inline void rdb_netstr_append_uint32(my_core::String* const out_netstr,
|
||||
const uint32 &val)
|
||||
{
|
||||
inline void rdb_netstr_append_uint32(my_core::String *const out_netstr,
|
||||
const uint32 &val) {
|
||||
DBUG_ASSERT(out_netstr != nullptr);
|
||||
|
||||
// Convert from host machine byte order (usually Little Endian) to network
|
||||
// byte order (Big Endian).
|
||||
uint32 net_val= htobe32(val);
|
||||
out_netstr->append(reinterpret_cast<char*>(&net_val), sizeof(net_val));
|
||||
uint32 net_val = htobe32(val);
|
||||
out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
|
||||
}
|
||||
|
||||
inline void rdb_netstr_append_uint16(my_core::String* const out_netstr,
|
||||
const uint16 &val)
|
||||
{
|
||||
inline void rdb_netstr_append_uint16(my_core::String *const out_netstr,
|
||||
const uint16 &val) {
|
||||
DBUG_ASSERT(out_netstr != nullptr);
|
||||
|
||||
// Convert from host machine byte order (usually Little Endian) to network
|
||||
// byte order (Big Endian).
|
||||
uint16 net_val= htobe16(val);
|
||||
out_netstr->append(reinterpret_cast<char*>(&net_val), sizeof(net_val));
|
||||
uint16 net_val = htobe16(val);
|
||||
out_netstr->append(reinterpret_cast<char *>(&net_val), sizeof(net_val));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Basic network buffer ("netbuf") write helper functions.
|
||||
*/
|
||||
|
||||
inline void rdb_netbuf_store_uint64(uchar* const dst_netbuf, const uint64 &n)
|
||||
{
|
||||
inline void rdb_netbuf_store_uint64(uchar *const dst_netbuf, const uint64 &n) {
|
||||
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||
|
||||
// Convert from host byte order (usually Little Endian) to network byte order
|
||||
// (Big Endian).
|
||||
uint64 net_val= htobe64(n);
|
||||
uint64 net_val = htobe64(n);
|
||||
memcpy(dst_netbuf, &net_val, sizeof(net_val));
|
||||
}
|
||||
|
||||
inline void rdb_netbuf_store_uint32(uchar* const dst_netbuf, const uint32 &n)
|
||||
{
|
||||
inline void rdb_netbuf_store_uint32(uchar *const dst_netbuf, const uint32 &n) {
|
||||
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||
|
||||
// Convert from host byte order (usually Little Endian) to network byte order
|
||||
// (Big Endian).
|
||||
uint32 net_val= htobe32(n);
|
||||
uint32 net_val = htobe32(n);
|
||||
memcpy(dst_netbuf, &net_val, sizeof(net_val));
|
||||
}
|
||||
|
||||
inline void rdb_netbuf_store_uint16(uchar* const dst_netbuf, const uint16 &n)
|
||||
{
|
||||
inline void rdb_netbuf_store_uint16(uchar *const dst_netbuf, const uint16 &n) {
|
||||
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||
|
||||
// Convert from host byte order (usually Little Endian) to network byte order
|
||||
// (Big Endian).
|
||||
uint16 net_val= htobe16(n);
|
||||
uint16 net_val = htobe16(n);
|
||||
memcpy(dst_netbuf, &net_val, sizeof(net_val));
|
||||
}
|
||||
|
||||
inline void rdb_netbuf_store_byte(uchar* const dst_netbuf, const uchar &c)
|
||||
{
|
||||
inline void rdb_netbuf_store_byte(uchar *const dst_netbuf, const uchar &c) {
|
||||
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||
|
||||
*dst_netbuf= c;
|
||||
*dst_netbuf = c;
|
||||
}
|
||||
|
||||
inline void rdb_netbuf_store_index(uchar* const dst_netbuf,
|
||||
const uint32 &number)
|
||||
{
|
||||
inline void rdb_netbuf_store_index(uchar *const dst_netbuf,
|
||||
const uint32 &number) {
|
||||
DBUG_ASSERT(dst_netbuf != nullptr);
|
||||
|
||||
rdb_netbuf_store_uint32(dst_netbuf, number);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Basic conversion helper functions from network byte order (Big Endian) to host
|
||||
machine byte order (usually Little Endian).
|
||||
*/
|
||||
|
||||
inline uint64 rdb_netbuf_to_uint64(const uchar* const netbuf)
|
||||
{
|
||||
inline uint64 rdb_netbuf_to_uint64(const uchar *const netbuf) {
|
||||
DBUG_ASSERT(netbuf != nullptr);
|
||||
|
||||
uint64 net_val;
|
||||
|
@ -128,8 +117,7 @@ inline uint64 rdb_netbuf_to_uint64(const uchar* const netbuf)
|
|||
return be64toh(net_val);
|
||||
}
|
||||
|
||||
inline uint32 rdb_netbuf_to_uint32(const uchar* const netbuf)
|
||||
{
|
||||
inline uint32 rdb_netbuf_to_uint32(const uchar *const netbuf) {
|
||||
DBUG_ASSERT(netbuf != nullptr);
|
||||
|
||||
uint32 net_val;
|
||||
|
@ -140,8 +128,7 @@ inline uint32 rdb_netbuf_to_uint32(const uchar* const netbuf)
|
|||
return be32toh(net_val);
|
||||
}
|
||||
|
||||
inline uint16 rdb_netbuf_to_uint16(const uchar* const netbuf)
|
||||
{
|
||||
inline uint16 rdb_netbuf_to_uint16(const uchar *const netbuf) {
|
||||
DBUG_ASSERT(netbuf != nullptr);
|
||||
|
||||
uint16 net_val;
|
||||
|
@ -152,14 +139,12 @@ inline uint16 rdb_netbuf_to_uint16(const uchar* const netbuf)
|
|||
return be16toh(net_val);
|
||||
}
|
||||
|
||||
inline uchar rdb_netbuf_to_byte(const uchar* const netbuf)
|
||||
{
|
||||
inline uchar rdb_netbuf_to_byte(const uchar *const netbuf) {
|
||||
DBUG_ASSERT(netbuf != nullptr);
|
||||
|
||||
return(uchar)netbuf[0];
|
||||
return (uchar)netbuf[0];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Basic network buffer ("netbuf") read helper functions.
|
||||
Network buffer stores data in Network Byte Order (Big Endian).
|
||||
|
@ -167,13 +152,12 @@ inline uchar rdb_netbuf_to_byte(const uchar* const netbuf)
|
|||
the netbuf pointer gets advanced to the following byte.
|
||||
*/
|
||||
|
||||
inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr)
|
||||
{
|
||||
inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr) {
|
||||
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||
|
||||
// Convert from network byte order (Big Endian) to host machine byte order
|
||||
// (usually Little Endian).
|
||||
const uint64 host_val= rdb_netbuf_to_uint64(*netbuf_ptr);
|
||||
const uint64 host_val = rdb_netbuf_to_uint64(*netbuf_ptr);
|
||||
|
||||
// Advance pointer.
|
||||
*netbuf_ptr += sizeof(host_val);
|
||||
|
@ -181,13 +165,12 @@ inline uint64 rdb_netbuf_read_uint64(const uchar **netbuf_ptr)
|
|||
return host_val;
|
||||
}
|
||||
|
||||
inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr)
|
||||
{
|
||||
inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr) {
|
||||
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||
|
||||
// Convert from network byte order (Big Endian) to host machine byte order
|
||||
// (usually Little Endian).
|
||||
const uint32 host_val= rdb_netbuf_to_uint32(*netbuf_ptr);
|
||||
const uint32 host_val = rdb_netbuf_to_uint32(*netbuf_ptr);
|
||||
|
||||
// Advance pointer.
|
||||
*netbuf_ptr += sizeof(host_val);
|
||||
|
@ -195,13 +178,12 @@ inline uint32 rdb_netbuf_read_uint32(const uchar **netbuf_ptr)
|
|||
return host_val;
|
||||
}
|
||||
|
||||
inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr)
|
||||
{
|
||||
inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr) {
|
||||
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||
|
||||
// Convert from network byte order (Big Endian) to host machine byte order
|
||||
// (usually Little Endian).
|
||||
const uint16 host_val= rdb_netbuf_to_uint16(*netbuf_ptr);
|
||||
const uint16 host_val = rdb_netbuf_to_uint16(*netbuf_ptr);
|
||||
|
||||
// Advance pointer.
|
||||
*netbuf_ptr += sizeof(host_val);
|
||||
|
@ -210,13 +192,12 @@ inline uint16 rdb_netbuf_read_uint16(const uchar **netbuf_ptr)
|
|||
}
|
||||
|
||||
inline void rdb_netbuf_read_gl_index(const uchar **netbuf_ptr,
|
||||
GL_INDEX_ID* const gl_index_id)
|
||||
{
|
||||
GL_INDEX_ID *const gl_index_id) {
|
||||
DBUG_ASSERT(gl_index_id != nullptr);
|
||||
DBUG_ASSERT(netbuf_ptr != nullptr);
|
||||
|
||||
gl_index_id->cf_id= rdb_netbuf_read_uint32(netbuf_ptr);
|
||||
gl_index_id->index_id= rdb_netbuf_read_uint32(netbuf_ptr);
|
||||
gl_index_id->cf_id = rdb_netbuf_read_uint32(netbuf_ptr);
|
||||
gl_index_id->index_id = rdb_netbuf_read_uint32(netbuf_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -225,17 +206,17 @@ inline void rdb_netbuf_read_gl_index(const uchar **netbuf_ptr,
|
|||
- it prevents one from reading beyond the end of the string.
|
||||
*/
|
||||
|
||||
class Rdb_string_reader
|
||||
{
|
||||
const char* m_ptr;
|
||||
class Rdb_string_reader {
|
||||
const char *m_ptr;
|
||||
uint m_len;
|
||||
private:
|
||||
Rdb_string_reader& operator=(const Rdb_string_reader&) = default;
|
||||
public:
|
||||
Rdb_string_reader(const Rdb_string_reader&) = default;
|
||||
|
||||
private:
|
||||
Rdb_string_reader &operator=(const Rdb_string_reader &) = default;
|
||||
|
||||
public:
|
||||
Rdb_string_reader(const Rdb_string_reader &) = default;
|
||||
/* named constructor */
|
||||
static Rdb_string_reader read_or_empty(const rocksdb::Slice* const slice)
|
||||
{
|
||||
static Rdb_string_reader read_or_empty(const rocksdb::Slice *const slice) {
|
||||
if (!slice) {
|
||||
return Rdb_string_reader("");
|
||||
} else {
|
||||
|
@ -243,72 +224,59 @@ class Rdb_string_reader
|
|||
}
|
||||
}
|
||||
|
||||
explicit Rdb_string_reader(const std::string &str)
|
||||
{
|
||||
m_len= str.length();
|
||||
if (m_len)
|
||||
{
|
||||
m_ptr= &str.at(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
explicit Rdb_string_reader(const std::string &str) {
|
||||
m_len = str.length();
|
||||
if (m_len) {
|
||||
m_ptr = &str.at(0);
|
||||
} else {
|
||||
/*
|
||||
One can a create a Rdb_string_reader for reading from an empty string
|
||||
(although attempts to read anything will fail).
|
||||
We must not access str.at(0), since len==0, we can set ptr to any
|
||||
value.
|
||||
*/
|
||||
m_ptr= nullptr;
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
explicit Rdb_string_reader(const rocksdb::Slice* const slice)
|
||||
{
|
||||
m_ptr= slice->data();
|
||||
m_len= slice->size();
|
||||
explicit Rdb_string_reader(const rocksdb::Slice *const slice) {
|
||||
m_ptr = slice->data();
|
||||
m_len = slice->size();
|
||||
}
|
||||
|
||||
/*
|
||||
Read the next @param size bytes. Returns pointer to the bytes read, or
|
||||
nullptr if the remaining string doesn't have that many bytes.
|
||||
*/
|
||||
const char *read(const uint &size)
|
||||
{
|
||||
const char *read(const uint &size) {
|
||||
const char *res;
|
||||
if (m_len < size)
|
||||
{
|
||||
res= nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
res= m_ptr;
|
||||
if (m_len < size) {
|
||||
res = nullptr;
|
||||
} else {
|
||||
res = m_ptr;
|
||||
m_ptr += size;
|
||||
m_len -= size;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool read_uint8(uint* const res)
|
||||
{
|
||||
bool read_uint8(uint *const res) {
|
||||
const uchar *p;
|
||||
if (!(p= reinterpret_cast<const uchar*>(read(1))))
|
||||
return true; // error
|
||||
else
|
||||
{
|
||||
*res= *p;
|
||||
return false; // Ok
|
||||
if (!(p = reinterpret_cast<const uchar *>(read(1))))
|
||||
return true; // error
|
||||
else {
|
||||
*res = *p;
|
||||
return false; // Ok
|
||||
}
|
||||
}
|
||||
|
||||
bool read_uint16(uint* const res)
|
||||
{
|
||||
bool read_uint16(uint *const res) {
|
||||
const uchar *p;
|
||||
if (!(p= reinterpret_cast<const uchar*>(read(2))))
|
||||
return true; // error
|
||||
else
|
||||
{
|
||||
*res= rdb_netbuf_to_uint16(p);
|
||||
return false; // Ok
|
||||
if (!(p = reinterpret_cast<const uchar *>(read(2))))
|
||||
return true; // error
|
||||
else {
|
||||
*res = rdb_netbuf_to_uint16(p);
|
||||
return false; // Ok
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +290,6 @@ class Rdb_string_reader
|
|||
const char *get_current_ptr() const { return m_ptr; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
A buffer one can write the data to.
|
||||
|
@ -338,132 +305,112 @@ class Rdb_string_reader
|
|||
|
||||
*/
|
||||
|
||||
class Rdb_string_writer
|
||||
{
|
||||
class Rdb_string_writer {
|
||||
std::vector<uchar> m_data;
|
||||
public:
|
||||
Rdb_string_writer(const Rdb_string_writer&) = delete;
|
||||
Rdb_string_writer& operator=(const Rdb_string_writer&) = delete;
|
||||
|
||||
public:
|
||||
Rdb_string_writer(const Rdb_string_writer &) = delete;
|
||||
Rdb_string_writer &operator=(const Rdb_string_writer &) = delete;
|
||||
Rdb_string_writer() = default;
|
||||
|
||||
void clear() { m_data.clear(); }
|
||||
void write_uint8(const uint &val)
|
||||
{
|
||||
void write_uint8(const uint &val) {
|
||||
m_data.push_back(static_cast<uchar>(val));
|
||||
}
|
||||
|
||||
void write_uint16(const uint &val)
|
||||
{
|
||||
const auto size= m_data.size();
|
||||
void write_uint16(const uint &val) {
|
||||
const auto size = m_data.size();
|
||||
m_data.resize(size + 2);
|
||||
rdb_netbuf_store_uint16(m_data.data() + size, val);
|
||||
}
|
||||
|
||||
void write_uint32(const uint &val)
|
||||
{
|
||||
const auto size= m_data.size();
|
||||
void write_uint32(const uint &val) {
|
||||
const auto size = m_data.size();
|
||||
m_data.resize(size + 4);
|
||||
rdb_netbuf_store_uint32(m_data.data() + size, val);
|
||||
}
|
||||
|
||||
void write(const uchar* const new_data, const size_t &len)
|
||||
{
|
||||
void write(const uchar *const new_data, const size_t &len) {
|
||||
DBUG_ASSERT(new_data != nullptr);
|
||||
m_data.insert(m_data.end(), new_data, new_data + len);
|
||||
}
|
||||
|
||||
uchar* ptr() { return m_data.data(); }
|
||||
uchar *ptr() { return m_data.data(); }
|
||||
size_t get_current_pos() const { return m_data.size(); }
|
||||
|
||||
void write_uint8_at(const size_t &pos, const uint &new_val)
|
||||
{
|
||||
void write_uint8_at(const size_t &pos, const uint &new_val) {
|
||||
// This function will only overwrite what was written
|
||||
DBUG_ASSERT(pos < get_current_pos());
|
||||
m_data.data()[pos]= new_val;
|
||||
m_data.data()[pos] = new_val;
|
||||
}
|
||||
|
||||
void write_uint16_at(const size_t &pos, const uint &new_val)
|
||||
{
|
||||
void write_uint16_at(const size_t &pos, const uint &new_val) {
|
||||
// This function will only overwrite what was written
|
||||
DBUG_ASSERT(pos < get_current_pos() && (pos + 1) < get_current_pos());
|
||||
rdb_netbuf_store_uint16(m_data.data() + pos, new_val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A helper class for writing bits into Rdb_string_writer.
|
||||
|
||||
The class assumes (but doesn't check) that nobody tries to write
|
||||
anything to the Rdb_string_writer that it is writing to.
|
||||
*/
|
||||
class Rdb_bit_writer
|
||||
{
|
||||
class Rdb_bit_writer {
|
||||
Rdb_string_writer *m_writer;
|
||||
uchar m_offset;
|
||||
public:
|
||||
Rdb_bit_writer(const Rdb_bit_writer&) = delete;
|
||||
Rdb_bit_writer& operator=(const Rdb_bit_writer&) = delete;
|
||||
|
||||
explicit Rdb_bit_writer(Rdb_string_writer* writer_arg)
|
||||
: m_writer(writer_arg),
|
||||
m_offset(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
Rdb_bit_writer(const Rdb_bit_writer &) = delete;
|
||||
Rdb_bit_writer &operator=(const Rdb_bit_writer &) = delete;
|
||||
|
||||
void write(uint size, const uint &value)
|
||||
{
|
||||
explicit Rdb_bit_writer(Rdb_string_writer *writer_arg)
|
||||
: m_writer(writer_arg), m_offset(0) {}
|
||||
|
||||
void write(uint size, const uint &value) {
|
||||
DBUG_ASSERT((value & ((1 << size) - 1)) == value);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
if (m_offset == 0)
|
||||
{
|
||||
while (size > 0) {
|
||||
if (m_offset == 0) {
|
||||
m_writer->write_uint8(0);
|
||||
}
|
||||
// number of bits to put in this byte
|
||||
const uint bits = std::min(size, (uint)(8 - m_offset));
|
||||
uchar* const last_byte= m_writer->ptr() + m_writer->get_current_pos() - 1;
|
||||
*last_byte |=
|
||||
(uchar) ((value >> (size - bits)) & ((1 << bits) - 1)) << m_offset;
|
||||
uchar *const last_byte =
|
||||
m_writer->ptr() + m_writer->get_current_pos() - 1;
|
||||
*last_byte |= (uchar)((value >> (size - bits)) & ((1 << bits) - 1))
|
||||
<< m_offset;
|
||||
size -= bits;
|
||||
m_offset = (m_offset + bits) & 0x7;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Rdb_bit_reader
|
||||
{
|
||||
class Rdb_bit_reader {
|
||||
const uchar *m_cur;
|
||||
uchar m_offset;
|
||||
uint m_ret;
|
||||
Rdb_string_reader* const m_reader;
|
||||
public:
|
||||
Rdb_bit_reader(const Rdb_bit_reader&) = delete;
|
||||
Rdb_bit_reader& operator=(const Rdb_bit_reader&) = delete;
|
||||
Rdb_string_reader *const m_reader;
|
||||
|
||||
explicit Rdb_bit_reader(Rdb_string_reader* const reader)
|
||||
: m_cur(nullptr),
|
||||
m_offset(0),
|
||||
m_reader(reader)
|
||||
{
|
||||
}
|
||||
public:
|
||||
Rdb_bit_reader(const Rdb_bit_reader &) = delete;
|
||||
Rdb_bit_reader &operator=(const Rdb_bit_reader &) = delete;
|
||||
|
||||
explicit Rdb_bit_reader(Rdb_string_reader *const reader)
|
||||
: m_cur(nullptr), m_offset(0), m_reader(reader) {}
|
||||
|
||||
// Returns a pointer to an uint containing the bits read. On subsequent
|
||||
// reads, the value being pointed to will be overwritten. Returns nullptr
|
||||
// on failure.
|
||||
uint *read(uint size)
|
||||
{
|
||||
m_ret= 0;
|
||||
uint *read(uint size) {
|
||||
m_ret = 0;
|
||||
DBUG_ASSERT(size <= 32);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
if (m_offset == 0)
|
||||
{
|
||||
m_cur= (const uchar *)m_reader->read(1);
|
||||
if (m_cur == nullptr)
|
||||
{
|
||||
while (size > 0) {
|
||||
if (m_offset == 0) {
|
||||
m_cur = (const uchar *)m_reader->read(1);
|
||||
if (m_cur == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -479,4 +426,4 @@ class Rdb_bit_reader
|
|||
}
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
/* This C++ files header file */
|
||||
|
@ -28,8 +28,7 @@
|
|||
namespace myrocks {
|
||||
|
||||
/* Check if ColumnFamily name says it's a reverse-ordered CF */
|
||||
bool Rdb_cf_manager::is_cf_name_reverse(const char* const name)
|
||||
{
|
||||
bool Rdb_cf_manager::is_cf_name_reverse(const char *const name) {
|
||||
/* nullptr means the default CF is used.. (TODO: can the default CF be
|
||||
* reverse?) */
|
||||
if (name && !strncmp(name, "rev:", 4))
|
||||
|
@ -43,9 +42,8 @@ static PSI_mutex_key ex_key_cfm;
|
|||
#endif
|
||||
|
||||
void Rdb_cf_manager::init(
|
||||
Rdb_cf_options* const cf_options,
|
||||
std::vector<rocksdb::ColumnFamilyHandle*>* const handles)
|
||||
{
|
||||
Rdb_cf_options *const cf_options,
|
||||
std::vector<rocksdb::ColumnFamilyHandle *> *const handles) {
|
||||
mysql_mutex_init(ex_key_cfm, &m_mutex, MY_MUTEX_INIT_FAST);
|
||||
|
||||
DBUG_ASSERT(cf_options != nullptr);
|
||||
|
@ -61,33 +59,28 @@ void Rdb_cf_manager::init(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Rdb_cf_manager::cleanup()
|
||||
{
|
||||
void Rdb_cf_manager::cleanup() {
|
||||
for (auto it : m_cf_name_map) {
|
||||
delete it.second;
|
||||
}
|
||||
mysql_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Generate Column Family name for per-index column families
|
||||
|
||||
@param res OUT Column Family name
|
||||
*/
|
||||
|
||||
void Rdb_cf_manager::get_per_index_cf_name(const std::string& db_table_name,
|
||||
const char* const index_name,
|
||||
std::string* const res)
|
||||
{
|
||||
void Rdb_cf_manager::get_per_index_cf_name(const std::string &db_table_name,
|
||||
const char *const index_name,
|
||||
std::string *const res) {
|
||||
DBUG_ASSERT(index_name != nullptr);
|
||||
DBUG_ASSERT(res != nullptr);
|
||||
|
||||
*res = db_table_name + "." + index_name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Find column family by name. If it doesn't exist, create it
|
||||
|
@ -95,53 +88,50 @@ void Rdb_cf_manager::get_per_index_cf_name(const std::string& db_table_name,
|
|||
@detail
|
||||
See Rdb_cf_manager::get_cf
|
||||
*/
|
||||
rocksdb::ColumnFamilyHandle*
|
||||
Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
|
||||
const char *cf_name,
|
||||
const std::string& db_table_name,
|
||||
const char* const index_name,
|
||||
bool* const is_automatic)
|
||||
{
|
||||
rocksdb::ColumnFamilyHandle *
|
||||
Rdb_cf_manager::get_or_create_cf(rocksdb::DB *const rdb, const char *cf_name,
|
||||
const std::string &db_table_name,
|
||||
const char *const index_name,
|
||||
bool *const is_automatic) {
|
||||
DBUG_ASSERT(rdb != nullptr);
|
||||
DBUG_ASSERT(is_automatic != nullptr);
|
||||
|
||||
rocksdb::ColumnFamilyHandle* cf_handle;
|
||||
rocksdb::ColumnFamilyHandle *cf_handle;
|
||||
|
||||
mysql_mutex_lock(&m_mutex);
|
||||
*is_automatic= false;
|
||||
*is_automatic = false;
|
||||
if (cf_name == nullptr)
|
||||
cf_name= DEFAULT_CF_NAME;
|
||||
cf_name = DEFAULT_CF_NAME;
|
||||
|
||||
std::string per_index_name;
|
||||
if (!strcmp(cf_name, PER_INDEX_CF_NAME))
|
||||
{
|
||||
if (!strcmp(cf_name, PER_INDEX_CF_NAME)) {
|
||||
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
|
||||
cf_name= per_index_name.c_str();
|
||||
*is_automatic= true;
|
||||
cf_name = per_index_name.c_str();
|
||||
*is_automatic = true;
|
||||
}
|
||||
|
||||
const auto it = m_cf_name_map.find(cf_name);
|
||||
if (it != m_cf_name_map.end())
|
||||
cf_handle= it->second;
|
||||
else
|
||||
{
|
||||
cf_handle = it->second;
|
||||
else {
|
||||
/* Create a Column Family. */
|
||||
const std::string cf_name_str(cf_name);
|
||||
rocksdb::ColumnFamilyOptions opts;
|
||||
m_cf_options->get_cf_options(cf_name_str, &opts);
|
||||
|
||||
sql_print_information("RocksDB: creating column family %s", cf_name_str.c_str());
|
||||
sql_print_information(" write_buffer_size=%ld", opts.write_buffer_size);
|
||||
sql_print_information("RocksDB: creating column family %s",
|
||||
cf_name_str.c_str());
|
||||
sql_print_information(" write_buffer_size=%ld", opts.write_buffer_size);
|
||||
sql_print_information(" target_file_size_base=%" PRIu64,
|
||||
opts.target_file_size_base);
|
||||
|
||||
const rocksdb::Status s=
|
||||
rdb->CreateColumnFamily(opts, cf_name_str, &cf_handle);
|
||||
const rocksdb::Status s =
|
||||
rdb->CreateColumnFamily(opts, cf_name_str, &cf_handle);
|
||||
if (s.ok()) {
|
||||
m_cf_name_map[cf_handle->GetName()] = cf_handle;
|
||||
m_cf_id_map[cf_handle->GetID()] = cf_handle;
|
||||
} else {
|
||||
cf_handle= nullptr;
|
||||
cf_handle = nullptr;
|
||||
}
|
||||
}
|
||||
mysql_mutex_unlock(&m_mutex);
|
||||
|
@ -149,7 +139,6 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
|
|||
return cf_handle;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find column family by its cf_name.
|
||||
|
||||
|
@ -162,27 +151,24 @@ Rdb_cf_manager::get_or_create_cf(rocksdb::DB* const rdb,
|
|||
db_table_name and index_name.
|
||||
*/
|
||||
|
||||
rocksdb::ColumnFamilyHandle*
|
||||
Rdb_cf_manager::get_cf(const char *cf_name,
|
||||
const std::string& db_table_name,
|
||||
const char* const index_name,
|
||||
bool* const is_automatic) const
|
||||
{
|
||||
rocksdb::ColumnFamilyHandle *
|
||||
Rdb_cf_manager::get_cf(const char *cf_name, const std::string &db_table_name,
|
||||
const char *const index_name,
|
||||
bool *const is_automatic) const {
|
||||
DBUG_ASSERT(is_automatic != nullptr);
|
||||
|
||||
rocksdb::ColumnFamilyHandle* cf_handle;
|
||||
rocksdb::ColumnFamilyHandle *cf_handle;
|
||||
|
||||
*is_automatic= false;
|
||||
*is_automatic = false;
|
||||
mysql_mutex_lock(&m_mutex);
|
||||
if (cf_name == nullptr)
|
||||
cf_name= DEFAULT_CF_NAME;
|
||||
cf_name = DEFAULT_CF_NAME;
|
||||
|
||||
std::string per_index_name;
|
||||
if (!strcmp(cf_name, PER_INDEX_CF_NAME))
|
||||
{
|
||||
if (!strcmp(cf_name, PER_INDEX_CF_NAME)) {
|
||||
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
|
||||
cf_name= per_index_name.c_str();
|
||||
*is_automatic= true;
|
||||
cf_name = per_index_name.c_str();
|
||||
*is_automatic = true;
|
||||
}
|
||||
|
||||
const auto it = m_cf_name_map.find(cf_name);
|
||||
|
@ -193,9 +179,8 @@ Rdb_cf_manager::get_cf(const char *cf_name,
|
|||
return cf_handle;
|
||||
}
|
||||
|
||||
rocksdb::ColumnFamilyHandle* Rdb_cf_manager::get_cf(const uint32_t &id) const
|
||||
{
|
||||
rocksdb::ColumnFamilyHandle* cf_handle = nullptr;
|
||||
rocksdb::ColumnFamilyHandle *Rdb_cf_manager::get_cf(const uint32_t &id) const {
|
||||
rocksdb::ColumnFamilyHandle *cf_handle = nullptr;
|
||||
|
||||
mysql_mutex_lock(&m_mutex);
|
||||
const auto it = m_cf_id_map.find(id);
|
||||
|
@ -206,9 +191,7 @@ rocksdb::ColumnFamilyHandle* Rdb_cf_manager::get_cf(const uint32_t &id) const
|
|||
return cf_handle;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
Rdb_cf_manager::get_cf_names(void) const
|
||||
{
|
||||
std::vector<std::string> Rdb_cf_manager::get_cf_names(void) const {
|
||||
std::vector<std::string> names;
|
||||
|
||||
mysql_mutex_lock(&m_mutex);
|
||||
|
@ -219,10 +202,9 @@ Rdb_cf_manager::get_cf_names(void) const
|
|||
return names;
|
||||
}
|
||||
|
||||
std::vector<rocksdb::ColumnFamilyHandle*>
|
||||
Rdb_cf_manager::get_all_cf(void) const
|
||||
{
|
||||
std::vector<rocksdb::ColumnFamilyHandle*> list;
|
||||
std::vector<rocksdb::ColumnFamilyHandle *>
|
||||
Rdb_cf_manager::get_all_cf(void) const {
|
||||
std::vector<rocksdb::ColumnFamilyHandle *> list;
|
||||
|
||||
mysql_mutex_lock(&m_mutex);
|
||||
for (auto it : m_cf_id_map) {
|
||||
|
@ -233,4 +215,4 @@ Rdb_cf_manager::get_all_cf(void) const
|
|||
return list;
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -46,33 +46,32 @@ namespace myrocks {
|
|||
- CFs are created in a synchronized way. We can't remove them, yet.
|
||||
*/
|
||||
|
||||
class Rdb_cf_manager
|
||||
{
|
||||
std::map<std::string, rocksdb::ColumnFamilyHandle*> m_cf_name_map;
|
||||
std::map<uint32_t, rocksdb::ColumnFamilyHandle*> m_cf_id_map;
|
||||
class Rdb_cf_manager {
|
||||
std::map<std::string, rocksdb::ColumnFamilyHandle *> m_cf_name_map;
|
||||
std::map<uint32_t, rocksdb::ColumnFamilyHandle *> m_cf_id_map;
|
||||
|
||||
mutable mysql_mutex_t m_mutex;
|
||||
|
||||
static
|
||||
void get_per_index_cf_name(const std::string& db_table_name,
|
||||
const char* const index_name,
|
||||
std::string* const res);
|
||||
static void get_per_index_cf_name(const std::string &db_table_name,
|
||||
const char *const index_name,
|
||||
std::string *const res);
|
||||
|
||||
Rdb_cf_options* m_cf_options= nullptr;
|
||||
Rdb_cf_options *m_cf_options = nullptr;
|
||||
|
||||
public:
|
||||
Rdb_cf_manager(const Rdb_cf_manager&) = delete;
|
||||
Rdb_cf_manager& operator=(const Rdb_cf_manager&) = delete;
|
||||
Rdb_cf_manager(const Rdb_cf_manager &) = delete;
|
||||
Rdb_cf_manager &operator=(const Rdb_cf_manager &) = delete;
|
||||
Rdb_cf_manager() = default;
|
||||
|
||||
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.
|
||||
*/
|
||||
void init(Rdb_cf_options* cf_options,
|
||||
std::vector<rocksdb::ColumnFamilyHandle*>* const handles);
|
||||
void init(Rdb_cf_options *cf_options,
|
||||
std::vector<rocksdb::ColumnFamilyHandle *> *const handles);
|
||||
void cleanup();
|
||||
|
||||
/*
|
||||
|
@ -80,33 +79,33 @@ public:
|
|||
- cf_name=nullptr means use default column family
|
||||
- cf_name=_auto_ means use 'dbname.tablename.indexname'
|
||||
*/
|
||||
rocksdb::ColumnFamilyHandle* get_or_create_cf(
|
||||
rocksdb::DB* const rdb, const char *cf_name,
|
||||
const std::string& db_table_name, const char* const index_name,
|
||||
bool* const is_automatic);
|
||||
rocksdb::ColumnFamilyHandle *
|
||||
get_or_create_cf(rocksdb::DB *const rdb, const char *cf_name,
|
||||
const std::string &db_table_name,
|
||||
const char *const index_name, bool *const is_automatic);
|
||||
|
||||
/* Used by table open */
|
||||
rocksdb::ColumnFamilyHandle* get_cf(const char *cf_name,
|
||||
const std::string& db_table_name,
|
||||
const char* const index_name,
|
||||
bool* const is_automatic) const;
|
||||
rocksdb::ColumnFamilyHandle *get_cf(const char *cf_name,
|
||||
const std::string &db_table_name,
|
||||
const char *const index_name,
|
||||
bool *const is_automatic) const;
|
||||
|
||||
/* Look up cf by id; used by datadic */
|
||||
rocksdb::ColumnFamilyHandle* get_cf(const uint32_t &id) const;
|
||||
rocksdb::ColumnFamilyHandle *get_cf(const uint32_t &id) const;
|
||||
|
||||
/* Used to iterate over column families for show status */
|
||||
std::vector<std::string> get_cf_names(void) const;
|
||||
|
||||
/* Used to iterate over column families */
|
||||
std::vector<rocksdb::ColumnFamilyHandle*> get_all_cf(void) const;
|
||||
std::vector<rocksdb::ColumnFamilyHandle *> get_all_cf(void) const;
|
||||
|
||||
// void drop_cf(); -- not implemented so far.
|
||||
|
||||
void get_cf_options(
|
||||
const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions* const opts) __attribute__((__nonnull__)) {
|
||||
m_cf_options->get_cf_options(cf_name, opts);
|
||||
void get_cf_options(const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions *const opts)
|
||||
MY_ATTRIBUTE((__nonnull__)) {
|
||||
m_cf_options->get_cf_options(cf_name, opts);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
/* This C++ files header file */
|
||||
|
@ -41,24 +41,23 @@ Rdb_pk_comparator Rdb_cf_options::s_pk_comparator;
|
|||
Rdb_rev_comparator Rdb_cf_options::s_rev_pk_comparator;
|
||||
|
||||
bool Rdb_cf_options::init(
|
||||
const rocksdb::BlockBasedTableOptions& table_options,
|
||||
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
|
||||
const char* const default_cf_options,
|
||||
const char* const override_cf_options)
|
||||
{
|
||||
const rocksdb::BlockBasedTableOptions &table_options,
|
||||
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
|
||||
const char *const default_cf_options,
|
||||
const char *const override_cf_options) {
|
||||
DBUG_ASSERT(default_cf_options != nullptr);
|
||||
DBUG_ASSERT(override_cf_options != nullptr);
|
||||
|
||||
m_default_cf_opts.comparator = &s_pk_comparator;
|
||||
m_default_cf_opts.compaction_filter_factory.reset(
|
||||
new Rdb_compact_filter_factory);
|
||||
new Rdb_compact_filter_factory);
|
||||
|
||||
m_default_cf_opts.table_factory.reset(
|
||||
rocksdb::NewBlockBasedTableFactory(table_options));
|
||||
rocksdb::NewBlockBasedTableFactory(table_options));
|
||||
|
||||
if (prop_coll_factory) {
|
||||
m_default_cf_opts.table_properties_collector_factories.push_back(
|
||||
prop_coll_factory);
|
||||
prop_coll_factory);
|
||||
}
|
||||
|
||||
if (!set_default(std::string(default_cf_options)) ||
|
||||
|
@ -70,34 +69,27 @@ bool Rdb_cf_options::init(
|
|||
}
|
||||
|
||||
void Rdb_cf_options::get(const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions* const opts)
|
||||
{
|
||||
rocksdb::ColumnFamilyOptions *const opts) {
|
||||
DBUG_ASSERT(opts != nullptr);
|
||||
|
||||
// set defaults
|
||||
rocksdb::GetColumnFamilyOptionsFromString(*opts,
|
||||
m_default_config,
|
||||
opts);
|
||||
rocksdb::GetColumnFamilyOptionsFromString(*opts, m_default_config, opts);
|
||||
|
||||
// set per-cf config if we have one
|
||||
Name_to_config_t::iterator it = m_name_map.find(cf_name);
|
||||
if (it != m_name_map.end()) {
|
||||
rocksdb::GetColumnFamilyOptionsFromString(*opts,
|
||||
it->second,
|
||||
opts);
|
||||
rocksdb::GetColumnFamilyOptionsFromString(*opts, it->second, opts);
|
||||
}
|
||||
}
|
||||
|
||||
bool Rdb_cf_options::set_default(const std::string &default_config)
|
||||
{
|
||||
bool Rdb_cf_options::set_default(const std::string &default_config) {
|
||||
rocksdb::ColumnFamilyOptions options;
|
||||
|
||||
if (!default_config.empty() &&
|
||||
!rocksdb::GetColumnFamilyOptionsFromString(options,
|
||||
default_config,
|
||||
&options).ok()) {
|
||||
fprintf(stderr,
|
||||
"Invalid default column family config: %s\n",
|
||||
!rocksdb::GetColumnFamilyOptionsFromString(options, default_config,
|
||||
&options)
|
||||
.ok()) {
|
||||
fprintf(stderr, "Invalid default column family config: %s\n",
|
||||
default_config.c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -107,8 +99,7 @@ bool Rdb_cf_options::set_default(const std::string &default_config)
|
|||
}
|
||||
|
||||
// Skip over any spaces in the input string.
|
||||
void Rdb_cf_options::skip_spaces(const std::string& input, size_t* const pos)
|
||||
{
|
||||
void Rdb_cf_options::skip_spaces(const std::string &input, size_t *const pos) {
|
||||
DBUG_ASSERT(pos != nullptr);
|
||||
|
||||
while (*pos < input.size() && isspace(input[*pos]))
|
||||
|
@ -118,10 +109,9 @@ void Rdb_cf_options::skip_spaces(const std::string& input, size_t* const pos)
|
|||
// Find a valid column family name. Note that all characters except a
|
||||
// semicolon are valid (should this change?) and all spaces are trimmed from
|
||||
// the beginning and end but are not removed between other characters.
|
||||
bool Rdb_cf_options::find_column_family(const std::string& input,
|
||||
size_t* const pos,
|
||||
std::string* const key)
|
||||
{
|
||||
bool Rdb_cf_options::find_column_family(const std::string &input,
|
||||
size_t *const pos,
|
||||
std::string *const key) {
|
||||
DBUG_ASSERT(pos != nullptr);
|
||||
DBUG_ASSERT(key != nullptr);
|
||||
|
||||
|
@ -129,15 +119,13 @@ bool Rdb_cf_options::find_column_family(const std::string& input,
|
|||
size_t end_pos = *pos - 1;
|
||||
|
||||
// Loop through the characters in the string until we see a '='.
|
||||
for ( ; *pos < input.size() && input[*pos] != '='; ++(*pos))
|
||||
{
|
||||
for (; *pos < input.size() && input[*pos] != '='; ++(*pos)) {
|
||||
// If this is not a space, move the end position to the current position.
|
||||
if (input[*pos] != ' ')
|
||||
end_pos = *pos;
|
||||
}
|
||||
|
||||
if (end_pos == beg_pos - 1)
|
||||
{
|
||||
if (end_pos == beg_pos - 1) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning("No column family found (options: %s)", input.c_str());
|
||||
return false;
|
||||
|
@ -150,18 +138,16 @@ bool Rdb_cf_options::find_column_family(const std::string& input,
|
|||
// Find a valid options portion. Everything is deemed valid within the options
|
||||
// portion until we hit as many close curly braces as we have seen open curly
|
||||
// braces.
|
||||
bool Rdb_cf_options::find_options(const std::string& input, size_t* const pos,
|
||||
std::string* const options)
|
||||
{
|
||||
bool Rdb_cf_options::find_options(const std::string &input, size_t *const pos,
|
||||
std::string *const options) {
|
||||
DBUG_ASSERT(pos != nullptr);
|
||||
DBUG_ASSERT(options != nullptr);
|
||||
|
||||
// Make sure we have an open curly brace at the current position.
|
||||
if (*pos < input.size() && input[*pos] != '{')
|
||||
{
|
||||
if (*pos < input.size() && input[*pos] != '{') {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning("Invalid cf options, '{' expected (options: %s)",
|
||||
input.c_str());
|
||||
input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -175,29 +161,26 @@ bool Rdb_cf_options::find_options(const std::string& input, size_t* const pos,
|
|||
|
||||
// Loop through the characters in the string until we find the appropriate
|
||||
// number of closing curly braces.
|
||||
while (*pos < input.size())
|
||||
{
|
||||
switch (input[*pos])
|
||||
{
|
||||
case '}':
|
||||
// If this is a closing curly brace and we bring the count down to zero
|
||||
// we can exit the loop with a valid options string.
|
||||
if (--brace_count == 0)
|
||||
{
|
||||
*options = input.substr(beg_pos, *pos - beg_pos);
|
||||
++(*pos); // Move past the last closing curly brace
|
||||
return true;
|
||||
}
|
||||
while (*pos < input.size()) {
|
||||
switch (input[*pos]) {
|
||||
case '}':
|
||||
// If this is a closing curly brace and we bring the count down to zero
|
||||
// we can exit the loop with a valid options string.
|
||||
if (--brace_count == 0) {
|
||||
*options = input.substr(beg_pos, *pos - beg_pos);
|
||||
++(*pos); // Move past the last closing curly brace
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case '{':
|
||||
// If this is an open curly brace increment the count.
|
||||
++brace_count;
|
||||
break;
|
||||
case '{':
|
||||
// If this is an open curly brace increment the count.
|
||||
++brace_count;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Move to the next character.
|
||||
|
@ -208,15 +191,14 @@ bool Rdb_cf_options::find_options(const std::string& input, size_t* const pos,
|
|||
// Generate an error.
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning("Mismatched cf options, '}' expected (options: %s)",
|
||||
input.c_str());
|
||||
input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
||||
size_t* const pos,
|
||||
std::string* const cf,
|
||||
std::string* const opt_str)
|
||||
{
|
||||
bool Rdb_cf_options::find_cf_options_pair(const std::string &input,
|
||||
size_t *const pos,
|
||||
std::string *const cf,
|
||||
std::string *const opt_str) {
|
||||
DBUG_ASSERT(pos != nullptr);
|
||||
DBUG_ASSERT(cf != nullptr);
|
||||
DBUG_ASSERT(opt_str != nullptr);
|
||||
|
@ -229,11 +211,10 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
|||
return false;
|
||||
|
||||
// If we are at the end of the input then we generate an error.
|
||||
if (*pos == input.size())
|
||||
{
|
||||
if (*pos == input.size()) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning("Invalid cf options, '=' expected (options: %s)",
|
||||
input.c_str());
|
||||
input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -250,13 +231,11 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
|||
skip_spaces(input, pos);
|
||||
|
||||
// We should either be at the end of the input string or at a semicolon.
|
||||
if (*pos < input.size())
|
||||
{
|
||||
if (input[*pos] != ';')
|
||||
{
|
||||
if (*pos < input.size()) {
|
||||
if (input[*pos] != ';') {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning("Invalid cf options, ';' expected (options: %s)",
|
||||
input.c_str());
|
||||
input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -266,8 +245,7 @@ bool Rdb_cf_options::find_cf_options_pair(const std::string& input,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Rdb_cf_options::set_override(const std::string &override_config)
|
||||
{
|
||||
bool Rdb_cf_options::set_override(const std::string &override_config) {
|
||||
// TODO(???): support updates?
|
||||
|
||||
std::string cf;
|
||||
|
@ -277,15 +255,13 @@ bool Rdb_cf_options::set_override(const std::string &override_config)
|
|||
|
||||
// Loop through the characters of the string until we reach the end.
|
||||
size_t pos = 0;
|
||||
while (pos < override_config.size())
|
||||
{
|
||||
while (pos < override_config.size()) {
|
||||
// Attempt to find <cf>={<opt_str>}.
|
||||
if (!find_cf_options_pair(override_config, &pos, &cf, &opt_str))
|
||||
return false;
|
||||
|
||||
// Generate an error if we have already seen this column family.
|
||||
if (configs.find(cf) != configs.end())
|
||||
{
|
||||
if (configs.find(cf) != configs.end()) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning(
|
||||
"Duplicate entry for %s in override options (options: %s)",
|
||||
|
@ -294,9 +270,8 @@ bool Rdb_cf_options::set_override(const std::string &override_config)
|
|||
}
|
||||
|
||||
// Generate an error if the <opt_str> is not valid according to RocksDB.
|
||||
if (!rocksdb::GetColumnFamilyOptionsFromString(
|
||||
options, opt_str, &options).ok())
|
||||
{
|
||||
if (!rocksdb::GetColumnFamilyOptionsFromString(options, opt_str, &options)
|
||||
.ok()) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning(
|
||||
"Invalid cf config for %s in override options (options: %s)",
|
||||
|
@ -314,29 +289,24 @@ bool Rdb_cf_options::set_override(const std::string &override_config)
|
|||
return true;
|
||||
}
|
||||
|
||||
const rocksdb::Comparator* Rdb_cf_options::get_cf_comparator(
|
||||
const std::string& cf_name)
|
||||
{
|
||||
if (Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str()))
|
||||
{
|
||||
const rocksdb::Comparator *
|
||||
Rdb_cf_options::get_cf_comparator(const std::string &cf_name) {
|
||||
if (Rdb_cf_manager::is_cf_name_reverse(cf_name.c_str())) {
|
||||
return &s_rev_pk_comparator;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return &s_pk_comparator;
|
||||
}
|
||||
}
|
||||
|
||||
void Rdb_cf_options::get_cf_options(const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions* const opts)
|
||||
{
|
||||
rocksdb::ColumnFamilyOptions *const opts) {
|
||||
DBUG_ASSERT(opts != nullptr);
|
||||
|
||||
*opts = m_default_cf_opts;
|
||||
get(cf_name, opts);
|
||||
|
||||
// Set the comparator according to 'rev:'
|
||||
opts->comparator= get_cf_comparator(cf_name);
|
||||
opts->comparator = get_cf_comparator(cf_name);
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -38,47 +38,47 @@ namespace myrocks {
|
|||
and also there is a default value which applies to column
|
||||
families not found in the map.
|
||||
*/
|
||||
class Rdb_cf_options
|
||||
{
|
||||
public:
|
||||
Rdb_cf_options(const Rdb_cf_options&) = delete;
|
||||
Rdb_cf_options& operator=(const Rdb_cf_options&) = delete;
|
||||
class Rdb_cf_options {
|
||||
public:
|
||||
Rdb_cf_options(const Rdb_cf_options &) = delete;
|
||||
Rdb_cf_options &operator=(const Rdb_cf_options &) = delete;
|
||||
Rdb_cf_options() = default;
|
||||
|
||||
void get(const std::string &cf_name, rocksdb::ColumnFamilyOptions* const opts);
|
||||
void get(const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions *const opts);
|
||||
|
||||
bool init(
|
||||
const rocksdb::BlockBasedTableOptions& table_options,
|
||||
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory> prop_coll_factory,
|
||||
const char* const default_cf_options,
|
||||
const char* const override_cf_options);
|
||||
bool init(const rocksdb::BlockBasedTableOptions &table_options,
|
||||
std::shared_ptr<rocksdb::TablePropertiesCollectorFactory>
|
||||
prop_coll_factory,
|
||||
const char *const default_cf_options,
|
||||
const char *const override_cf_options);
|
||||
|
||||
const rocksdb::ColumnFamilyOptions& get_defaults() const {
|
||||
const rocksdb::ColumnFamilyOptions &get_defaults() const {
|
||||
return m_default_cf_opts;
|
||||
}
|
||||
|
||||
static const rocksdb::Comparator* get_cf_comparator(
|
||||
const std::string& cf_name);
|
||||
static const rocksdb::Comparator *
|
||||
get_cf_comparator(const std::string &cf_name);
|
||||
|
||||
void get_cf_options(
|
||||
const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions* const opts) __attribute__((__nonnull__));
|
||||
void get_cf_options(const std::string &cf_name,
|
||||
rocksdb::ColumnFamilyOptions *const opts)
|
||||
MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
private:
|
||||
private:
|
||||
bool set_default(const std::string &default_config);
|
||||
bool set_override(const std::string &overide_config);
|
||||
|
||||
/* Helper string manipulation functions */
|
||||
static void skip_spaces(const std::string& input, size_t* const pos);
|
||||
static bool find_column_family(const std::string& input, size_t* const pos,
|
||||
std::string* const key);
|
||||
static bool find_options(const std::string& input, size_t* const pos,
|
||||
std::string* const options);
|
||||
static bool find_cf_options_pair(const std::string& input, size_t* const pos,
|
||||
std::string* const cf,
|
||||
std::string* const opt_str);
|
||||
static void skip_spaces(const std::string &input, size_t *const pos);
|
||||
static bool find_column_family(const std::string &input, size_t *const pos,
|
||||
std::string *const key);
|
||||
static bool find_options(const std::string &input, size_t *const pos,
|
||||
std::string *const options);
|
||||
static bool find_cf_options_pair(const std::string &input, size_t *const pos,
|
||||
std::string *const cf,
|
||||
std::string *const opt_str);
|
||||
|
||||
private:
|
||||
private:
|
||||
static Rdb_pk_comparator s_pk_comparator;
|
||||
static Rdb_rev_comparator s_rev_pk_comparator;
|
||||
|
||||
|
@ -93,4 +93,4 @@ class Rdb_cf_options
|
|||
rocksdb::ColumnFamilyOptions m_default_cf_opts;
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
/* C++ system header files */
|
||||
|
@ -32,11 +32,10 @@
|
|||
|
||||
namespace myrocks {
|
||||
|
||||
class Rdb_compact_filter : public rocksdb::CompactionFilter
|
||||
{
|
||||
public:
|
||||
Rdb_compact_filter(const Rdb_compact_filter&) = delete;
|
||||
Rdb_compact_filter& operator=(const Rdb_compact_filter&) = delete;
|
||||
class Rdb_compact_filter : public rocksdb::CompactionFilter {
|
||||
public:
|
||||
Rdb_compact_filter(const Rdb_compact_filter &) = delete;
|
||||
Rdb_compact_filter &operator=(const Rdb_compact_filter &) = delete;
|
||||
|
||||
explicit Rdb_compact_filter(uint32_t _cf_id) : m_cf_id(_cf_id) {}
|
||||
~Rdb_compact_filter() {}
|
||||
|
@ -45,32 +44,28 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
|
|||
// V1 Filter is thread safe on our usage (creating from Factory).
|
||||
// Make sure to protect instance variables when switching to thread
|
||||
// unsafe in the future.
|
||||
virtual bool Filter(int level,
|
||||
const rocksdb::Slice& key,
|
||||
const rocksdb::Slice& existing_value,
|
||||
std::string* new_value,
|
||||
bool* value_changed) const override
|
||||
{
|
||||
virtual bool Filter(int level, const rocksdb::Slice &key,
|
||||
const rocksdb::Slice &existing_value,
|
||||
std::string *new_value,
|
||||
bool *value_changed) const override {
|
||||
DBUG_ASSERT(key.size() >= sizeof(uint32));
|
||||
|
||||
GL_INDEX_ID gl_index_id;
|
||||
gl_index_id.cf_id= m_cf_id;
|
||||
gl_index_id.index_id= rdb_netbuf_to_uint32((const uchar*)key.data());
|
||||
gl_index_id.cf_id = m_cf_id;
|
||||
gl_index_id.index_id = rdb_netbuf_to_uint32((const uchar *)key.data());
|
||||
DBUG_ASSERT(gl_index_id.index_id >= 1);
|
||||
|
||||
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)
|
||||
{
|
||||
m_num_deleted= 0;
|
||||
if (m_num_deleted > 0) {
|
||||
m_num_deleted = 0;
|
||||
}
|
||||
m_should_delete=
|
||||
m_should_delete =
|
||||
rdb_get_dict_manager()->is_drop_index_ongoing(gl_index_id);
|
||||
m_prev_index= gl_index_id;
|
||||
m_prev_index = gl_index_id;
|
||||
}
|
||||
|
||||
if (m_should_delete)
|
||||
{
|
||||
if (m_should_delete) {
|
||||
m_num_deleted++;
|
||||
}
|
||||
|
||||
|
@ -79,42 +74,35 @@ class Rdb_compact_filter : public rocksdb::CompactionFilter
|
|||
|
||||
virtual bool IgnoreSnapshots() const override { return true; }
|
||||
|
||||
virtual const char* Name() const override
|
||||
{
|
||||
return "Rdb_compact_filter";
|
||||
}
|
||||
virtual const char *Name() const override { return "Rdb_compact_filter"; }
|
||||
|
||||
private:
|
||||
private:
|
||||
// Column family for this compaction filter
|
||||
const uint32_t m_cf_id;
|
||||
// Index id of the previous record
|
||||
mutable GL_INDEX_ID m_prev_index= {0, 0};
|
||||
mutable GL_INDEX_ID m_prev_index = {0, 0};
|
||||
// Number of rows deleted for the same index id
|
||||
mutable uint64 m_num_deleted= 0;
|
||||
mutable uint64 m_num_deleted = 0;
|
||||
// Current index id should be deleted or not (should be deleted if true)
|
||||
mutable bool m_should_delete= false;
|
||||
mutable bool m_should_delete = false;
|
||||
};
|
||||
|
||||
class Rdb_compact_filter_factory : public rocksdb::CompactionFilterFactory
|
||||
{
|
||||
public:
|
||||
Rdb_compact_filter_factory(const Rdb_compact_filter_factory&) = delete;
|
||||
Rdb_compact_filter_factory& operator=(const Rdb_compact_filter_factory&) = delete;
|
||||
class Rdb_compact_filter_factory : public rocksdb::CompactionFilterFactory {
|
||||
public:
|
||||
Rdb_compact_filter_factory(const Rdb_compact_filter_factory &) = delete;
|
||||
Rdb_compact_filter_factory &
|
||||
operator=(const Rdb_compact_filter_factory &) = delete;
|
||||
Rdb_compact_filter_factory() {}
|
||||
|
||||
~Rdb_compact_filter_factory() {}
|
||||
|
||||
const char* Name() const override
|
||||
{
|
||||
return "Rdb_compact_filter_factory";
|
||||
}
|
||||
const char *Name() const override { return "Rdb_compact_filter_factory"; }
|
||||
|
||||
std::unique_ptr<rocksdb::CompactionFilter> CreateCompactionFilter(
|
||||
const rocksdb::CompactionFilter::Context& context) override
|
||||
{
|
||||
const rocksdb::CompactionFilter::Context &context) override {
|
||||
return std::unique_ptr<rocksdb::CompactionFilter>(
|
||||
new Rdb_compact_filter(context.column_family_id));
|
||||
new Rdb_compact_filter(context.column_family_id));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
/* RocksDB header files */
|
||||
#include "rocksdb/comparator.h"
|
||||
|
||||
/* MyRocks header files */
|
||||
#include "./rdb_utils.h"
|
||||
|
||||
namespace myrocks {
|
||||
|
||||
/*
|
||||
|
@ -32,70 +35,65 @@ namespace myrocks {
|
|||
(todo: knowledge about this format is shared between this class and
|
||||
Rdb_key_def)
|
||||
*/
|
||||
class Rdb_pk_comparator : public rocksdb::Comparator
|
||||
{
|
||||
public:
|
||||
Rdb_pk_comparator(const Rdb_pk_comparator&) = delete;
|
||||
Rdb_pk_comparator& operator=(const Rdb_pk_comparator&) = delete;
|
||||
class Rdb_pk_comparator : public rocksdb::Comparator {
|
||||
public:
|
||||
Rdb_pk_comparator(const Rdb_pk_comparator &) = delete;
|
||||
Rdb_pk_comparator &operator=(const Rdb_pk_comparator &) = delete;
|
||||
Rdb_pk_comparator() = default;
|
||||
|
||||
static int bytewise_compare(const rocksdb::Slice& a, const rocksdb::Slice& b)
|
||||
{
|
||||
const size_t a_size= a.size();
|
||||
const size_t b_size= b.size();
|
||||
const size_t len= (a_size < b_size) ? a_size : b_size;
|
||||
static int bytewise_compare(const rocksdb::Slice &a,
|
||||
const rocksdb::Slice &b) {
|
||||
const size_t a_size = a.size();
|
||||
const size_t b_size = b.size();
|
||||
const size_t len = (a_size < b_size) ? a_size : b_size;
|
||||
int res;
|
||||
|
||||
if ((res= memcmp(a.data(), b.data(), len)))
|
||||
if ((res = memcmp(a.data(), b.data(), len)))
|
||||
return res;
|
||||
|
||||
/* Ok, res== 0 */
|
||||
if (a_size != b_size)
|
||||
{
|
||||
return a_size < b_size? -1 : 1;
|
||||
if (a_size != b_size) {
|
||||
return a_size < b_size ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Override virtual methods of interest */
|
||||
|
||||
int Compare(const rocksdb::Slice& a, const rocksdb::Slice& b) const override
|
||||
{
|
||||
return bytewise_compare(a,b);
|
||||
int Compare(const rocksdb::Slice &a, const rocksdb::Slice &b) const override {
|
||||
return bytewise_compare(a, b);
|
||||
}
|
||||
|
||||
const char* Name() const override { return "RocksDB_SE_v3.10"; }
|
||||
const char *Name() const override { return "RocksDB_SE_v3.10"; }
|
||||
|
||||
//TODO: advanced funcs:
|
||||
// TODO: advanced funcs:
|
||||
// - FindShortestSeparator
|
||||
// - FindShortSuccessor
|
||||
|
||||
// for now, do-nothing implementations:
|
||||
void FindShortestSeparator(std::string* start,
|
||||
const rocksdb::Slice& limit) const override {}
|
||||
void FindShortSuccessor(std::string* key) const override {}
|
||||
void FindShortestSeparator(std::string *start,
|
||||
const rocksdb::Slice &limit) const override {}
|
||||
void FindShortSuccessor(std::string *key) const override {}
|
||||
};
|
||||
|
||||
class Rdb_rev_comparator : public rocksdb::Comparator
|
||||
{
|
||||
public:
|
||||
Rdb_rev_comparator(const Rdb_rev_comparator&) = delete;
|
||||
Rdb_rev_comparator& operator=(const Rdb_rev_comparator&) = delete;
|
||||
class Rdb_rev_comparator : public rocksdb::Comparator {
|
||||
public:
|
||||
Rdb_rev_comparator(const Rdb_rev_comparator &) = delete;
|
||||
Rdb_rev_comparator &operator=(const Rdb_rev_comparator &) = delete;
|
||||
Rdb_rev_comparator() = default;
|
||||
|
||||
static int bytewise_compare(const rocksdb::Slice& a, const rocksdb::Slice& b)
|
||||
{
|
||||
static int bytewise_compare(const rocksdb::Slice &a,
|
||||
const rocksdb::Slice &b) {
|
||||
return -Rdb_pk_comparator::bytewise_compare(a, b);
|
||||
}
|
||||
|
||||
int Compare(const rocksdb::Slice& a, const rocksdb::Slice& b) const override
|
||||
{
|
||||
int Compare(const rocksdb::Slice &a, const rocksdb::Slice &b) const override {
|
||||
return -Rdb_pk_comparator::bytewise_compare(a, b);
|
||||
}
|
||||
const char* Name() const override { return "rev:RocksDB_SE_v3.10"; }
|
||||
void FindShortestSeparator(std::string* start,
|
||||
const rocksdb::Slice& limit) const override {}
|
||||
void FindShortSuccessor(std::string* key) const override {}
|
||||
const char *Name() const override { return "rev:RocksDB_SE_v3.10"; }
|
||||
void FindShortestSeparator(std::string *start,
|
||||
const rocksdb::Slice &limit) const override {}
|
||||
void FindShortSuccessor(std::string *key) const override {}
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
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_global;
|
||||
extern struct st_mysql_plugin rdb_i_s_cfoptions;
|
||||
extern struct st_mysql_plugin rdb_i_s_compact_stats;
|
||||
extern struct st_mysql_plugin rdb_i_s_global_info;
|
||||
extern struct st_mysql_plugin rdb_i_s_ddl;
|
||||
extern struct st_mysql_plugin rdb_i_s_index_file_map;
|
||||
extern struct st_mysql_plugin rdb_i_s_lock_info;
|
||||
extern struct st_mysql_plugin rdb_i_s_trx_info;
|
||||
} // namespace myrocks
|
||||
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -17,47 +17,37 @@
|
|||
/* This C++ file's header file */
|
||||
#include "./rdb_index_merge.h"
|
||||
|
||||
/* MySQL header files */
|
||||
#include "../sql/sql_class.h"
|
||||
|
||||
/* MyRocks header files */
|
||||
#include "./ha_rocksdb.h"
|
||||
#include "./rdb_datadic.h"
|
||||
|
||||
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_combine_read_size,
|
||||
const rocksdb::Comparator* const comparator) :
|
||||
m_tmpfile_path(tmpfile_path),
|
||||
m_merge_buf_size(merge_buf_size),
|
||||
m_merge_combine_read_size(merge_combine_read_size),
|
||||
m_comparator(comparator),
|
||||
m_rec_buf_unsorted(nullptr),
|
||||
m_output_buf(nullptr)
|
||||
{
|
||||
}
|
||||
const rocksdb::Comparator *const comparator)
|
||||
: m_tmpfile_path(tmpfile_path), m_merge_buf_size(merge_buf_size),
|
||||
m_merge_combine_read_size(merge_combine_read_size),
|
||||
m_comparator(comparator), m_rec_buf_unsorted(nullptr),
|
||||
m_output_buf(nullptr) {}
|
||||
|
||||
Rdb_index_merge::~Rdb_index_merge()
|
||||
{
|
||||
Rdb_index_merge::~Rdb_index_merge() {
|
||||
/*
|
||||
Close tmp file, we don't need to worry about deletion, mysql handles it.
|
||||
*/
|
||||
my_close(m_merge_file.fd, MYF(MY_WME));
|
||||
|
||||
/* There should be no records left in the offset tree */
|
||||
DBUG_ASSERT(m_offset_tree.empty());
|
||||
|
||||
/* There should be no pointers left on the merge heap */
|
||||
DBUG_ASSERT(m_merge_min_heap.empty());
|
||||
}
|
||||
|
||||
int Rdb_index_merge::init()
|
||||
{
|
||||
int Rdb_index_merge::init() {
|
||||
/*
|
||||
Create a temporary merge file on disk to store sorted chunks during
|
||||
inplace index creation.
|
||||
*/
|
||||
if (merge_file_create())
|
||||
{
|
||||
if (merge_file_create()) {
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -66,46 +56,41 @@ int Rdb_index_merge::init()
|
|||
to disk. They will be written to disk sorted. A sorted tree is used to
|
||||
keep track of the offset of each record within the unsorted buffer.
|
||||
*/
|
||||
m_rec_buf_unsorted= std::shared_ptr<merge_buf_info>(
|
||||
new merge_buf_info(m_merge_buf_size));
|
||||
m_rec_buf_unsorted =
|
||||
std::shared_ptr<merge_buf_info>(new merge_buf_info(m_merge_buf_size));
|
||||
|
||||
/*
|
||||
Allocate output buffer that will contain sorted block that is written to
|
||||
disk.
|
||||
*/
|
||||
m_output_buf= std::shared_ptr<merge_buf_info>(
|
||||
new merge_buf_info(m_merge_buf_size));
|
||||
m_output_buf =
|
||||
std::shared_ptr<merge_buf_info>(new merge_buf_info(m_merge_buf_size));
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a merge file in the given location.
|
||||
*/
|
||||
int Rdb_index_merge::merge_file_create()
|
||||
{
|
||||
int Rdb_index_merge::merge_file_create() {
|
||||
DBUG_ASSERT(m_merge_file.fd == -1);
|
||||
|
||||
int fd;
|
||||
/* If no path set for tmpfile, use mysql_tmpdir by default */
|
||||
if (m_tmpfile_path == nullptr)
|
||||
{
|
||||
if (m_tmpfile_path == nullptr) {
|
||||
fd = mysql_tmpfile("myrocks");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fd = mysql_tmpfile_path(m_tmpfile_path, "myrocks");
|
||||
}
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
if (fd < 0) {
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
m_merge_file.fd = fd;
|
||||
m_merge_file.num_sort_buffers = 0;
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,9 +100,7 @@ int Rdb_index_merge::merge_file_create()
|
|||
If buffer in memory is full, write the buffer out to disk sorted using the
|
||||
offset tree, and clear the tree. (Happens in merge_buf_write)
|
||||
*/
|
||||
int Rdb_index_merge::add(const rocksdb::Slice& key,
|
||||
const rocksdb::Slice& val)
|
||||
{
|
||||
int Rdb_index_merge::add(const rocksdb::Slice &key, const rocksdb::Slice &val) {
|
||||
/* Adding a record after heap is already created results in error */
|
||||
DBUG_ASSERT(m_merge_min_heap.empty());
|
||||
|
||||
|
@ -125,33 +108,30 @@ int Rdb_index_merge::add(const rocksdb::Slice& key,
|
|||
Check if sort buffer is going to be out of space, if so write it
|
||||
out to disk in sorted order using offset tree.
|
||||
*/
|
||||
const uint total_offset=
|
||||
RDB_MERGE_CHUNK_LEN + m_rec_buf_unsorted->curr_offset +
|
||||
RDB_MERGE_KEY_DELIMITER + RDB_MERGE_VAL_DELIMITER +
|
||||
key.size() + val.size();
|
||||
if (total_offset >= m_rec_buf_unsorted->total_size)
|
||||
{
|
||||
const uint total_offset = RDB_MERGE_CHUNK_LEN +
|
||||
m_rec_buf_unsorted->curr_offset +
|
||||
RDB_MERGE_KEY_DELIMITER + RDB_MERGE_VAL_DELIMITER +
|
||||
key.size() + val.size();
|
||||
if (total_offset >= m_rec_buf_unsorted->total_size) {
|
||||
/*
|
||||
If the offset tree is empty here, that means that the proposed key to
|
||||
add is too large for the buffer.
|
||||
*/
|
||||
if (m_offset_tree.empty())
|
||||
{
|
||||
if (m_offset_tree.empty()) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Sort buffer size is too small to process merge. "
|
||||
"Please set merge buffer size to a higher value.");
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (merge_buf_write())
|
||||
{
|
||||
if (merge_buf_write()) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error writing sort buffer to disk.");
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
const ulonglong rec_offset= m_rec_buf_unsorted->curr_offset;
|
||||
const ulonglong rec_offset = m_rec_buf_unsorted->curr_offset;
|
||||
|
||||
/*
|
||||
Store key and value in temporary unsorted in memory buffer pointed to by
|
||||
|
@ -163,14 +143,13 @@ int Rdb_index_merge::add(const rocksdb::Slice& key,
|
|||
m_offset_tree.emplace(m_rec_buf_unsorted->block.get() + rec_offset,
|
||||
m_comparator);
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Sort + write merge buffer chunk out to disk.
|
||||
*/
|
||||
int Rdb_index_merge::merge_buf_write()
|
||||
{
|
||||
int Rdb_index_merge::merge_buf_write() {
|
||||
DBUG_ASSERT(m_merge_file.fd != -1);
|
||||
DBUG_ASSERT(m_rec_buf_unsorted != nullptr);
|
||||
DBUG_ASSERT(m_output_buf != nullptr);
|
||||
|
@ -185,8 +164,7 @@ int Rdb_index_merge::merge_buf_write()
|
|||
Iterate through the offset tree. Should be ordered by the secondary key
|
||||
at this point.
|
||||
*/
|
||||
for (const auto& rec : m_offset_tree)
|
||||
{
|
||||
for (const auto &rec : m_offset_tree) {
|
||||
DBUG_ASSERT(m_output_buf->curr_offset <= m_merge_buf_size);
|
||||
|
||||
/* Read record from offset (should never fail) */
|
||||
|
@ -207,8 +185,7 @@ int Rdb_index_merge::merge_buf_write()
|
|||
then write into the respective merge buffer.
|
||||
*/
|
||||
if (my_seek(m_merge_file.fd, m_merge_file.num_sort_buffers * m_merge_buf_size,
|
||||
SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
|
||||
{
|
||||
SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error seeking to location in merge file on disk.");
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
|
@ -220,9 +197,8 @@ int Rdb_index_merge::merge_buf_write()
|
|||
burst.
|
||||
*/
|
||||
if (my_write(m_merge_file.fd, m_output_buf->block.get(),
|
||||
m_output_buf->total_size, MYF(MY_WME | MY_NABP)) ||
|
||||
mysql_file_sync(m_merge_file.fd, MYF(MY_WME)))
|
||||
{
|
||||
m_output_buf->total_size, MYF(MY_WME | MY_NABP)) ||
|
||||
mysql_file_sync(m_merge_file.fd, MYF(MY_WME))) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error writing sorted merge buffer to disk.");
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
|
@ -234,23 +210,21 @@ int Rdb_index_merge::merge_buf_write()
|
|||
/* Reset everything for next run */
|
||||
merge_reset();
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Prepare n-way merge of n sorted buffers on disk, using a heap sorted by
|
||||
secondary key records.
|
||||
*/
|
||||
int Rdb_index_merge::merge_heap_prepare()
|
||||
{
|
||||
int Rdb_index_merge::merge_heap_prepare() {
|
||||
DBUG_ASSERT(m_merge_min_heap.empty());
|
||||
|
||||
/*
|
||||
If the offset tree is not empty, there are still some records that need to
|
||||
be written to disk. Write them out now.
|
||||
*/
|
||||
if (!m_offset_tree.empty() && merge_buf_write())
|
||||
{
|
||||
if (!m_offset_tree.empty() && merge_buf_write()) {
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -260,39 +234,34 @@ int Rdb_index_merge::merge_heap_prepare()
|
|||
For an n-way merge, we need to read chunks of each merge file
|
||||
simultaneously.
|
||||
*/
|
||||
ulonglong chunk_size= m_merge_combine_read_size/
|
||||
m_merge_file.num_sort_buffers;
|
||||
if (chunk_size >= m_merge_buf_size)
|
||||
{
|
||||
chunk_size= m_merge_buf_size;
|
||||
ulonglong chunk_size =
|
||||
m_merge_combine_read_size / m_merge_file.num_sort_buffers;
|
||||
if (chunk_size >= m_merge_buf_size) {
|
||||
chunk_size = m_merge_buf_size;
|
||||
}
|
||||
|
||||
/* Allocate buffers for each chunk */
|
||||
for (ulonglong i = 0; i < m_merge_file.num_sort_buffers; i++)
|
||||
{
|
||||
const auto entry= std::make_shared<merge_heap_entry>(m_comparator);
|
||||
for (ulonglong i = 0; i < m_merge_file.num_sort_buffers; i++) {
|
||||
const auto entry = std::make_shared<merge_heap_entry>(m_comparator);
|
||||
|
||||
/*
|
||||
Read chunk_size bytes from each chunk on disk, and place inside
|
||||
respective chunk buffer.
|
||||
*/
|
||||
const size_t total_size=
|
||||
entry->prepare(m_merge_file.fd, i * m_merge_buf_size, chunk_size);
|
||||
const size_t total_size =
|
||||
entry->prepare(m_merge_file.fd, i * m_merge_buf_size, chunk_size);
|
||||
|
||||
if (total_size == (size_t) - 1)
|
||||
{
|
||||
if (total_size == (size_t)-1) {
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/* Can reach this condition if an index was added on table w/ no rows */
|
||||
if (total_size - RDB_MERGE_CHUNK_LEN == 0)
|
||||
{
|
||||
if (total_size - RDB_MERGE_CHUNK_LEN == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the first record from each buffer to initially populate the heap */
|
||||
if (entry->read_rec(&entry->key, &entry->val))
|
||||
{
|
||||
if (entry->read_rec(&entry->key, &entry->val)) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Chunk size is too small to process merge.");
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
|
@ -301,14 +270,14 @@ int Rdb_index_merge::merge_heap_prepare()
|
|||
m_merge_min_heap.push(std::move(entry));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create and/or iterate through keys in the merge heap.
|
||||
*/
|
||||
int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
||||
{
|
||||
int Rdb_index_merge::next(rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val) {
|
||||
/*
|
||||
If table fits in one sort buffer, we can optimize by writing
|
||||
the sort buffer directly through to the sstfilewriter instead of
|
||||
|
@ -317,20 +286,18 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
|||
If there are no sort buffer records (alters on empty tables),
|
||||
also exit here.
|
||||
*/
|
||||
if (m_merge_file.num_sort_buffers == 0)
|
||||
{
|
||||
if (m_offset_tree.empty())
|
||||
{
|
||||
if (m_merge_file.num_sort_buffers == 0) {
|
||||
if (m_offset_tree.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto rec= m_offset_tree.begin();
|
||||
const auto rec = m_offset_tree.begin();
|
||||
|
||||
/* Read record from offset */
|
||||
merge_read_rec(rec->block, key, val);
|
||||
|
||||
m_offset_tree.erase(rec);
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int res;
|
||||
|
@ -340,10 +307,8 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
|||
of the external sort. Populate the heap with initial values from each
|
||||
disk chunk.
|
||||
*/
|
||||
if (m_merge_min_heap.empty())
|
||||
{
|
||||
if ((res= merge_heap_prepare()))
|
||||
{
|
||||
if (m_merge_min_heap.empty()) {
|
||||
if ((res = merge_heap_prepare())) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error during preparation of heap.");
|
||||
return res;
|
||||
|
@ -354,7 +319,7 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
|||
inside the SST file yet.
|
||||
*/
|
||||
merge_heap_top(key, val);
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(!m_merge_min_heap.empty());
|
||||
|
@ -364,14 +329,13 @@ int Rdb_index_merge::next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
|||
/**
|
||||
Get current top record from the heap.
|
||||
*/
|
||||
void Rdb_index_merge::merge_heap_top(rocksdb::Slice* const key,
|
||||
rocksdb::Slice* const val)
|
||||
{
|
||||
void Rdb_index_merge::merge_heap_top(rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val) {
|
||||
DBUG_ASSERT(!m_merge_min_heap.empty());
|
||||
|
||||
const std::shared_ptr<merge_heap_entry>& entry= m_merge_min_heap.top();
|
||||
*key= entry->key;
|
||||
*val= entry->val;
|
||||
const std::shared_ptr<merge_heap_entry> &entry = m_merge_min_heap.top();
|
||||
*key = entry->key;
|
||||
*val = entry->val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,14 +344,13 @@ void Rdb_index_merge::merge_heap_top(rocksdb::Slice* const key,
|
|||
|
||||
Returns -1 when there are no more records in the heap.
|
||||
*/
|
||||
int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
|
||||
rocksdb::Slice* const val)
|
||||
{
|
||||
int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val) {
|
||||
/*
|
||||
Make a new reference to shared ptr so it doesn't get destroyed
|
||||
during pop(). We are going to push this entry back onto the heap.
|
||||
*/
|
||||
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();
|
||||
m_merge_min_heap.pop();
|
||||
|
||||
/*
|
||||
|
@ -397,15 +360,13 @@ int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
|
|||
Return without adding entry back onto heap.
|
||||
If heap is also empty, we must be finished with merge.
|
||||
*/
|
||||
if (entry->chunk_info->is_chunk_finished())
|
||||
{
|
||||
if (m_merge_min_heap.empty())
|
||||
{
|
||||
if (entry->chunk_info->is_chunk_finished()) {
|
||||
if (m_merge_min_heap.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
merge_heap_top(key, val);
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -417,16 +378,13 @@ int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
|
|||
If merge_read_rec fails, it means the either the chunk was cut off
|
||||
or we've reached the end of the respective chunk.
|
||||
*/
|
||||
if (entry->read_rec(&entry->key, &entry->val))
|
||||
{
|
||||
if (entry->read_next_chunk_from_disk(m_merge_file.fd))
|
||||
{
|
||||
if (entry->read_rec(&entry->key, &entry->val)) {
|
||||
if (entry->read_next_chunk_from_disk(m_merge_file.fd)) {
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/* Try reading record again, should never fail. */
|
||||
if (entry->read_rec(&entry->key, &entry->val))
|
||||
{
|
||||
if (entry->read_rec(&entry->key, &entry->val)) {
|
||||
return HA_ERR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -436,52 +394,46 @@ int Rdb_index_merge::merge_heap_pop_and_get_next(rocksdb::Slice* const key,
|
|||
|
||||
/* Return the current top record on heap */
|
||||
merge_heap_top(key, val);
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int Rdb_index_merge::merge_heap_entry::read_next_chunk_from_disk(File fd)
|
||||
{
|
||||
if (chunk_info->read_next_chunk_from_disk(fd))
|
||||
{
|
||||
return 1;
|
||||
int Rdb_index_merge::merge_heap_entry::read_next_chunk_from_disk(File fd) {
|
||||
if (chunk_info->read_next_chunk_from_disk(fd)) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
block= chunk_info->block.get();
|
||||
return 0;
|
||||
block = chunk_info->block.get();
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int Rdb_index_merge::merge_buf_info::read_next_chunk_from_disk(File fd)
|
||||
{
|
||||
int Rdb_index_merge::merge_buf_info::read_next_chunk_from_disk(File fd) {
|
||||
disk_curr_offset += curr_offset;
|
||||
|
||||
if (my_seek(fd, disk_curr_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
|
||||
{
|
||||
if (my_seek(fd, disk_curr_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error seeking to location in merge file on disk.");
|
||||
return 1;
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Overwrite the old block */
|
||||
const size_t bytes_read= my_read(fd, block.get(), block_len, MYF(MY_WME));
|
||||
if (bytes_read == (size_t) -1)
|
||||
{
|
||||
const size_t bytes_read = my_read(fd, block.get(), block_len, MYF(MY_WME));
|
||||
if (bytes_read == (size_t)-1) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error reading merge file from disk.");
|
||||
return 1;
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
curr_offset= 0;
|
||||
return 0;
|
||||
curr_offset = 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Get records from offset within sort buffer and compare them.
|
||||
Sort by least to greatest.
|
||||
*/
|
||||
int Rdb_index_merge::merge_record_compare(const uchar* const a_block,
|
||||
const uchar* const b_block,
|
||||
const rocksdb::Comparator* const comparator)
|
||||
{
|
||||
int Rdb_index_merge::merge_record_compare(
|
||||
const uchar *const a_block, const uchar *const b_block,
|
||||
const rocksdb::Comparator *const comparator) {
|
||||
return comparator->Compare(as_slice(a_block), as_slice(b_block));
|
||||
}
|
||||
|
||||
|
@ -489,114 +441,103 @@ int Rdb_index_merge::merge_record_compare(const uchar* const a_block,
|
|||
Given an offset in a merge sort buffer, read out the keys + values.
|
||||
After this, block will point to the next record in the buffer.
|
||||
**/
|
||||
void Rdb_index_merge::merge_read_rec(const uchar* const block,
|
||||
rocksdb::Slice* const key,
|
||||
rocksdb::Slice* const val)
|
||||
{
|
||||
void Rdb_index_merge::merge_read_rec(const uchar *const block,
|
||||
rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val) {
|
||||
/* Read key at block offset into key slice and the value into value slice*/
|
||||
read_slice(key, block);
|
||||
read_slice(val, block + RDB_MERGE_REC_DELIMITER + key->size());
|
||||
}
|
||||
|
||||
void Rdb_index_merge::read_slice(rocksdb::Slice* slice, const uchar* block_ptr)
|
||||
{
|
||||
void Rdb_index_merge::read_slice(rocksdb::Slice *slice,
|
||||
const uchar *block_ptr) {
|
||||
uint64 slice_len;
|
||||
merge_read_uint64(&block_ptr, &slice_len);
|
||||
|
||||
*slice= rocksdb::Slice(reinterpret_cast<const char*>(block_ptr), slice_len);
|
||||
*slice = rocksdb::Slice(reinterpret_cast<const char *>(block_ptr), slice_len);
|
||||
}
|
||||
|
||||
int Rdb_index_merge::merge_heap_entry::read_rec(rocksdb::Slice* const key,
|
||||
rocksdb::Slice* const val)
|
||||
{
|
||||
const uchar* block_ptr= block;
|
||||
int Rdb_index_merge::merge_heap_entry::read_rec(rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val) {
|
||||
const uchar *block_ptr = block;
|
||||
const auto orig_offset = chunk_info->curr_offset;
|
||||
const auto orig_block = block;
|
||||
|
||||
/* Read key at block offset into key slice and the value into value slice*/
|
||||
if (read_slice(key, &block_ptr) != 0)
|
||||
{
|
||||
return 1;
|
||||
if (read_slice(key, &block_ptr) != 0) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
chunk_info->curr_offset += (uintptr_t) block_ptr - (uintptr_t) block;
|
||||
block += (uintptr_t) block_ptr - (uintptr_t) block;
|
||||
chunk_info->curr_offset += (uintptr_t)block_ptr - (uintptr_t)block;
|
||||
block += (uintptr_t)block_ptr - (uintptr_t)block;
|
||||
|
||||
if (read_slice(val, &block_ptr) != 0)
|
||||
{
|
||||
chunk_info->curr_offset= orig_offset;
|
||||
block= orig_block;
|
||||
return 1;
|
||||
if (read_slice(val, &block_ptr) != 0) {
|
||||
chunk_info->curr_offset = orig_offset;
|
||||
block = orig_block;
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
chunk_info->curr_offset += (uintptr_t) block_ptr - (uintptr_t) block;
|
||||
block += (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;
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int Rdb_index_merge::merge_heap_entry::read_slice(rocksdb::Slice* const slice,
|
||||
const uchar** block_ptr)
|
||||
{
|
||||
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER))
|
||||
{
|
||||
return 1;
|
||||
int Rdb_index_merge::merge_heap_entry::read_slice(rocksdb::Slice *const slice,
|
||||
const uchar **block_ptr) {
|
||||
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER)) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
uint64 slice_len;
|
||||
merge_read_uint64(block_ptr, &slice_len);
|
||||
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER + slice_len))
|
||||
{
|
||||
return 1;
|
||||
if (!chunk_info->has_space(RDB_MERGE_REC_DELIMITER + slice_len)) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
*slice= rocksdb::Slice(reinterpret_cast<const char*>(*block_ptr), slice_len);
|
||||
*slice =
|
||||
rocksdb::Slice(reinterpret_cast<const char *>(*block_ptr), slice_len);
|
||||
*block_ptr += slice_len;
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
size_t Rdb_index_merge::merge_heap_entry::prepare(File fd, ulonglong f_offset,
|
||||
ulonglong chunk_size)
|
||||
{
|
||||
chunk_info= std::make_shared<merge_buf_info>(chunk_size);
|
||||
ulonglong chunk_size) {
|
||||
chunk_info = std::make_shared<merge_buf_info>(chunk_size);
|
||||
const size_t res = chunk_info->prepare(fd, f_offset);
|
||||
if (res != (size_t) - 1)
|
||||
{
|
||||
block= chunk_info->block.get() + RDB_MERGE_CHUNK_LEN;
|
||||
if (res != (size_t)-1) {
|
||||
block = chunk_info->block.get() + RDB_MERGE_CHUNK_LEN;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset)
|
||||
{
|
||||
disk_start_offset= f_offset;
|
||||
disk_curr_offset= f_offset;
|
||||
size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset) {
|
||||
disk_start_offset = f_offset;
|
||||
disk_curr_offset = f_offset;
|
||||
|
||||
/*
|
||||
Need to position cursor to the chunk it needs to be at on filesystem
|
||||
then read 'chunk_size' bytes into the respective chunk buffer.
|
||||
*/
|
||||
if (my_seek(fd, f_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
|
||||
{
|
||||
if (my_seek(fd, f_offset, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error seeking to location in merge file on disk.");
|
||||
return (size_t) - 1;
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
const size_t bytes_read= my_read(fd, block.get(), total_size, MYF(MY_WME));
|
||||
if (bytes_read == (size_t) - 1)
|
||||
{
|
||||
const size_t bytes_read = my_read(fd, block.get(), total_size, MYF(MY_WME));
|
||||
if (bytes_read == (size_t)-1) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_error("Error reading merge file from disk.");
|
||||
return (size_t) - 1;
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
/*
|
||||
Read the first 8 bytes of each chunk, this gives us the actual
|
||||
size of each chunk.
|
||||
*/
|
||||
const uchar *block_ptr= block.get();
|
||||
const uchar *block_ptr = block.get();
|
||||
merge_read_uint64(&block_ptr, &total_size);
|
||||
curr_offset += RDB_MERGE_CHUNK_LEN;
|
||||
return total_size;
|
||||
|
@ -604,27 +545,23 @@ size_t Rdb_index_merge::merge_buf_info::prepare(File fd, ulonglong f_offset)
|
|||
|
||||
/* Store key and value w/ their respective delimiters at the given offset */
|
||||
void Rdb_index_merge::merge_buf_info::store_key_value(
|
||||
const rocksdb::Slice& key, const rocksdb::Slice& val)
|
||||
{
|
||||
const rocksdb::Slice &key, const rocksdb::Slice &val) {
|
||||
store_slice(key);
|
||||
store_slice(val);
|
||||
}
|
||||
|
||||
void Rdb_index_merge::merge_buf_info::store_slice(const rocksdb::Slice& slice)
|
||||
{
|
||||
void Rdb_index_merge::merge_buf_info::store_slice(const rocksdb::Slice &slice) {
|
||||
/* Store length delimiter */
|
||||
merge_store_uint64(&block[curr_offset], slice.size());
|
||||
|
||||
/* Store slice data */
|
||||
memcpy(&block[curr_offset + RDB_MERGE_REC_DELIMITER], slice.data(),
|
||||
slice.size());
|
||||
slice.size());
|
||||
|
||||
curr_offset += slice.size() + RDB_MERGE_REC_DELIMITER;
|
||||
}
|
||||
|
||||
|
||||
void Rdb_index_merge::merge_reset()
|
||||
{
|
||||
void Rdb_index_merge::merge_reset() {
|
||||
/*
|
||||
Either error, or all values in the sort buffer have been written to disk,
|
||||
so we need to clear the offset tree.
|
||||
|
@ -632,16 +569,14 @@ void Rdb_index_merge::merge_reset()
|
|||
m_offset_tree.clear();
|
||||
|
||||
/* Reset sort buffer block */
|
||||
if (m_rec_buf_unsorted && m_rec_buf_unsorted->block)
|
||||
{
|
||||
m_rec_buf_unsorted->curr_offset= 0;
|
||||
if (m_rec_buf_unsorted && m_rec_buf_unsorted->block) {
|
||||
m_rec_buf_unsorted->curr_offset = 0;
|
||||
}
|
||||
|
||||
/* Reset output buf */
|
||||
if (m_output_buf && m_output_buf->block)
|
||||
{
|
||||
m_output_buf->curr_offset= 0;
|
||||
if (m_output_buf && m_output_buf->block) {
|
||||
m_output_buf->curr_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
/* MySQL header files */
|
||||
#include "../sql/log.h"
|
||||
#include "./handler.h" /* handler */
|
||||
#include "./my_global.h" /* ulonglong */
|
||||
#include "./handler.h" /* handler */
|
||||
#include "./my_global.h" /* ulonglong */
|
||||
|
||||
/* C++ standard header files */
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
/* RocksDB header files */
|
||||
#include "rocksdb/db.h"
|
||||
|
@ -46,13 +46,13 @@ class Rdb_key_def;
|
|||
class Rdb_tbl_def;
|
||||
|
||||
class Rdb_index_merge {
|
||||
Rdb_index_merge(const Rdb_index_merge& p)= delete;
|
||||
Rdb_index_merge& operator=(const Rdb_index_merge& p)= delete;
|
||||
Rdb_index_merge(const Rdb_index_merge &p) = delete;
|
||||
Rdb_index_merge &operator=(const Rdb_index_merge &p) = delete;
|
||||
|
||||
public:
|
||||
public:
|
||||
/* Information about temporary files used in external merge sort */
|
||||
struct merge_file_info {
|
||||
File fd= -1; /* file descriptor */
|
||||
File fd = -1; /* file descriptor */
|
||||
ulong num_sort_buffers; /* number of sort buffers in temp file */
|
||||
};
|
||||
|
||||
|
@ -60,40 +60,37 @@ class Rdb_index_merge {
|
|||
struct merge_buf_info {
|
||||
/* heap memory allocated for main memory sort/merge */
|
||||
std::unique_ptr<uchar[]> block;
|
||||
const ulonglong block_len; /* amount of data bytes allocated for block above */
|
||||
const ulonglong
|
||||
block_len; /* amount of data bytes allocated for block above */
|
||||
ulonglong curr_offset; /* offset of the record pointer for the block */
|
||||
ulonglong disk_start_offset; /* where the chunk starts on disk */
|
||||
ulonglong disk_curr_offset; /* current offset on disk */
|
||||
ulonglong total_size; /* total # of data bytes in chunk */
|
||||
ulonglong disk_curr_offset; /* current offset on disk */
|
||||
ulonglong total_size; /* total # of data bytes in chunk */
|
||||
|
||||
void store_key_value(const rocksdb::Slice& key, const rocksdb::Slice& val)
|
||||
__attribute__((__nonnull__));
|
||||
void store_key_value(const rocksdb::Slice &key, const rocksdb::Slice &val)
|
||||
MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
void store_slice(const rocksdb::Slice& slice)
|
||||
__attribute__((__nonnull__));
|
||||
void store_slice(const rocksdb::Slice &slice) MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
size_t prepare(File fd, ulonglong f_offset)
|
||||
__attribute__((__nonnull__));
|
||||
size_t prepare(File fd, ulonglong f_offset) MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
int read_next_chunk_from_disk(File fd)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
inline bool is_chunk_finished() const
|
||||
{
|
||||
inline bool is_chunk_finished() const {
|
||||
return curr_offset + disk_curr_offset - disk_start_offset == total_size;
|
||||
}
|
||||
|
||||
inline bool has_space(uint64 needed) const
|
||||
{
|
||||
inline bool has_space(uint64 needed) const {
|
||||
return curr_offset + needed <= block_len;
|
||||
}
|
||||
|
||||
explicit merge_buf_info(const ulonglong merge_block_size) :
|
||||
block(nullptr), block_len(merge_block_size), curr_offset(0),
|
||||
disk_start_offset(0), disk_curr_offset(0), total_size(merge_block_size)
|
||||
{
|
||||
explicit merge_buf_info(const ulonglong merge_block_size)
|
||||
: block(nullptr), block_len(merge_block_size), curr_offset(0),
|
||||
disk_start_offset(0), disk_curr_offset(0),
|
||||
total_size(merge_block_size) {
|
||||
/* Will throw an exception if it runs out of memory here */
|
||||
block= std::unique_ptr<uchar[]>(new uchar[merge_block_size]);
|
||||
block = std::unique_ptr<uchar[]>(new uchar[merge_block_size]);
|
||||
|
||||
/* Initialize entire buffer to 0 to avoid valgrind errors */
|
||||
memset(block.get(), 0, merge_block_size);
|
||||
|
@ -101,132 +98,121 @@ class Rdb_index_merge {
|
|||
};
|
||||
|
||||
/* Represents an entry in the heap during merge phase of external sort */
|
||||
struct merge_heap_entry
|
||||
{
|
||||
struct merge_heap_entry {
|
||||
std::shared_ptr<merge_buf_info> chunk_info; /* pointer to buffer info */
|
||||
uchar* block; /* pointer to heap memory where record is stored */
|
||||
const rocksdb::Comparator* const comparator;
|
||||
uchar *block; /* pointer to heap memory where record is stored */
|
||||
const rocksdb::Comparator *const comparator;
|
||||
rocksdb::Slice key; /* current key pointed to by block ptr */
|
||||
rocksdb::Slice val;
|
||||
|
||||
size_t prepare(File fd, ulonglong f_offset, ulonglong chunk_size)
|
||||
__attribute__((__nonnull__));
|
||||
MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
int read_next_chunk_from_disk(File fd)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int read_rec(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int read_rec(rocksdb::Slice *const key, rocksdb::Slice *const val)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int read_slice(rocksdb::Slice* const slice, const uchar** block_ptr)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int read_slice(rocksdb::Slice *const slice, const uchar **block_ptr)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
explicit merge_heap_entry(const rocksdb::Comparator* const comparator) :
|
||||
chunk_info(nullptr), block(nullptr), comparator(comparator) {}
|
||||
explicit merge_heap_entry(const rocksdb::Comparator *const comparator)
|
||||
: chunk_info(nullptr), block(nullptr), comparator(comparator) {}
|
||||
};
|
||||
|
||||
struct merge_heap_comparator
|
||||
{
|
||||
bool operator() (const std::shared_ptr<merge_heap_entry>& lhs,
|
||||
const std::shared_ptr<merge_heap_entry>& rhs)
|
||||
{
|
||||
struct merge_heap_comparator {
|
||||
bool operator()(const std::shared_ptr<merge_heap_entry> &lhs,
|
||||
const std::shared_ptr<merge_heap_entry> &rhs) {
|
||||
return lhs->comparator->Compare(rhs->key, lhs->key) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* Represents a record in unsorted buffer */
|
||||
struct merge_record
|
||||
{
|
||||
uchar* block; /* points to offset of key in sort buffer */
|
||||
const rocksdb::Comparator* const comparator;
|
||||
struct merge_record {
|
||||
uchar *block; /* points to offset of key in sort buffer */
|
||||
const rocksdb::Comparator *const comparator;
|
||||
|
||||
bool operator< (const merge_record &record) const
|
||||
{
|
||||
bool operator<(const merge_record &record) const {
|
||||
return merge_record_compare(this->block, record.block, comparator) < 0;
|
||||
}
|
||||
|
||||
merge_record(uchar* const block,
|
||||
const rocksdb::Comparator* const comparator) :
|
||||
block(block), comparator(comparator) {}
|
||||
merge_record(uchar *const block,
|
||||
const rocksdb::Comparator *const comparator)
|
||||
: block(block), comparator(comparator) {}
|
||||
};
|
||||
|
||||
private:
|
||||
const char* m_tmpfile_path;
|
||||
const ulonglong m_merge_buf_size;
|
||||
const ulonglong m_merge_combine_read_size;
|
||||
const rocksdb::Comparator* m_comparator;
|
||||
struct merge_file_info m_merge_file;
|
||||
std::shared_ptr<merge_buf_info> m_rec_buf_unsorted;
|
||||
std::shared_ptr<merge_buf_info> m_output_buf;
|
||||
std::set<merge_record> m_offset_tree;
|
||||
private:
|
||||
const char *m_tmpfile_path;
|
||||
const ulonglong m_merge_buf_size;
|
||||
const ulonglong m_merge_combine_read_size;
|
||||
const rocksdb::Comparator *m_comparator;
|
||||
struct merge_file_info m_merge_file;
|
||||
std::shared_ptr<merge_buf_info> m_rec_buf_unsorted;
|
||||
std::shared_ptr<merge_buf_info> m_output_buf;
|
||||
std::set<merge_record> m_offset_tree;
|
||||
std::priority_queue<std::shared_ptr<merge_heap_entry>,
|
||||
std::vector<std::shared_ptr<merge_heap_entry>>,
|
||||
merge_heap_comparator> m_merge_min_heap;
|
||||
merge_heap_comparator>
|
||||
m_merge_min_heap;
|
||||
|
||||
static inline void merge_store_uint64(uchar* const dst, uint64 n)
|
||||
{
|
||||
static inline void merge_store_uint64(uchar *const dst, uint64 n) {
|
||||
memcpy(dst, &n, sizeof(n));
|
||||
}
|
||||
|
||||
static inline void merge_read_uint64(const uchar **buf_ptr, uint64* const dst)
|
||||
{
|
||||
static inline void merge_read_uint64(const uchar **buf_ptr,
|
||||
uint64 *const dst) {
|
||||
DBUG_ASSERT(buf_ptr != nullptr);
|
||||
memcpy(dst, *buf_ptr, sizeof(uint64));
|
||||
*buf_ptr += sizeof(uint64);
|
||||
}
|
||||
|
||||
static inline rocksdb::Slice as_slice(const uchar* block)
|
||||
{
|
||||
static inline rocksdb::Slice as_slice(const uchar *block) {
|
||||
uint64 len;
|
||||
merge_read_uint64(&block, &len);
|
||||
|
||||
return rocksdb::Slice(reinterpret_cast<const char*>(block), len);
|
||||
return rocksdb::Slice(reinterpret_cast<const char *>(block), len);
|
||||
}
|
||||
|
||||
static int merge_record_compare(const uchar* a_block, const uchar* b_block,
|
||||
const rocksdb::Comparator* const comparator)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
static int merge_record_compare(const uchar *a_block, const uchar *b_block,
|
||||
const rocksdb::Comparator *const comparator)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
void merge_read_rec(const uchar* const block, rocksdb::Slice* const key,
|
||||
rocksdb::Slice* const val)
|
||||
__attribute__((__nonnull__));
|
||||
void merge_read_rec(const uchar *const block, rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val) MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
void read_slice(rocksdb::Slice* slice, const uchar* block_ptr)
|
||||
__attribute__((__nonnull__));
|
||||
void read_slice(rocksdb::Slice *slice, const uchar *block_ptr)
|
||||
MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
public:
|
||||
Rdb_index_merge(const char* const tmpfile_path,
|
||||
public:
|
||||
Rdb_index_merge(const char *const tmpfile_path,
|
||||
const ulonglong &merge_buf_size,
|
||||
const ulonglong &merge_combine_read_size,
|
||||
const rocksdb::Comparator* const comparator);
|
||||
const rocksdb::Comparator *const comparator);
|
||||
~Rdb_index_merge();
|
||||
|
||||
int init()
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int init() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int merge_file_create()
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int merge_file_create() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int add(const rocksdb::Slice& key, const rocksdb::Slice& val)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int add(const rocksdb::Slice &key, const rocksdb::Slice &val)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int merge_buf_write()
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int merge_buf_write() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int next(rocksdb::Slice* const key, rocksdb::Slice* const val)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int next(rocksdb::Slice *const key, rocksdb::Slice *const val)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
int merge_heap_prepare()
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int merge_heap_prepare() MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
void merge_heap_top(rocksdb::Slice* key, rocksdb::Slice* val)
|
||||
__attribute__((__nonnull__));
|
||||
void merge_heap_top(rocksdb::Slice *key, rocksdb::Slice *val)
|
||||
MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
int merge_heap_pop_and_get_next(rocksdb::Slice* const key,
|
||||
rocksdb::Slice* const val)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
int merge_heap_pop_and_get_next(rocksdb::Slice *const key,
|
||||
rocksdb::Slice *const val)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
void merge_reset();
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -17,43 +17,35 @@
|
|||
/* This C++ file's header file */
|
||||
#include "./rdb_mutex_wrapper.h"
|
||||
|
||||
/* MySQL header files */
|
||||
#include "../sql/sql_class.h"
|
||||
#include "../sql/replication.h"
|
||||
|
||||
/* MyRocks header files */
|
||||
#include "./ha_rocksdb.h"
|
||||
#include "./rdb_utils.h"
|
||||
|
||||
// Internal MySQL APIs not exposed in any header.
|
||||
extern "C"
|
||||
{
|
||||
void thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, mysql_mutex_t *mutex,
|
||||
const PSI_stage_info *stage, PSI_stage_info *old_stage);
|
||||
void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage);
|
||||
}
|
||||
|
||||
using namespace rocksdb;
|
||||
|
||||
namespace myrocks {
|
||||
|
||||
static
|
||||
PSI_stage_info stage_waiting_on_row_lock2= { 0, "Waiting for row lock", 0};
|
||||
static PSI_stage_info stage_waiting_on_row_lock2 = {0, "Waiting for row lock",
|
||||
0};
|
||||
|
||||
static const int64_t MICROSECS= 1000*1000;
|
||||
static const int64_t ONE_SECOND_IN_MICROSECS = 1000 * 1000;
|
||||
// A timeout as long as one full non-leap year worth of microseconds is as
|
||||
// good as infinite timeout.
|
||||
static const int64_t BIG_TIMEOUT= MICROSECS * 60 * 60 * 24 * 365;
|
||||
static const int64_t ONE_YEAR_IN_MICROSECS =
|
||||
ONE_SECOND_IN_MICROSECS * 60 * 60 * 24 * 365;
|
||||
|
||||
Rdb_cond_var::Rdb_cond_var() {
|
||||
mysql_cond_init(0, &m_cond, nullptr);
|
||||
}
|
||||
Rdb_cond_var::Rdb_cond_var() { mysql_cond_init(0, &m_cond, nullptr); }
|
||||
|
||||
Rdb_cond_var::~Rdb_cond_var() {
|
||||
mysql_cond_destroy(&m_cond);
|
||||
}
|
||||
Rdb_cond_var::~Rdb_cond_var() { mysql_cond_destroy(&m_cond); }
|
||||
|
||||
Status Rdb_cond_var::Wait(const std::shared_ptr<TransactionDBMutex> mutex_arg) {
|
||||
return WaitFor(mutex_arg, BIG_TIMEOUT);
|
||||
return WaitFor(mutex_arg, ONE_YEAR_IN_MICROSECS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Wait on condition variable. The caller must make sure that we own
|
||||
|
@ -70,32 +62,30 @@ Status Rdb_cond_var::Wait(const std::shared_ptr<TransactionDBMutex> mutex_arg) {
|
|||
|
||||
Status
|
||||
Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
||||
int64_t timeout_micros)
|
||||
{
|
||||
auto *mutex_obj= reinterpret_cast<Rdb_mutex*>(mutex_arg.get());
|
||||
int64_t timeout_micros) {
|
||||
auto *mutex_obj = reinterpret_cast<Rdb_mutex *>(mutex_arg.get());
|
||||
DBUG_ASSERT(mutex_obj != nullptr);
|
||||
|
||||
mysql_mutex_t * const mutex_ptr= &mutex_obj->m_mutex;
|
||||
mysql_mutex_t *const mutex_ptr = &mutex_obj->m_mutex;
|
||||
|
||||
int res= 0;
|
||||
int res = 0;
|
||||
struct timespec wait_timeout;
|
||||
|
||||
if (timeout_micros < 0)
|
||||
timeout_micros= BIG_TIMEOUT;
|
||||
set_timespec_nsec(wait_timeout, timeout_micros*1000);
|
||||
timeout_micros = ONE_YEAR_IN_MICROSECS;
|
||||
set_timespec_nsec(wait_timeout, timeout_micros * 1000);
|
||||
|
||||
#ifndef STANDALONE_UNITTEST
|
||||
PSI_stage_info old_stage;
|
||||
mysql_mutex_assert_owner(mutex_ptr);
|
||||
|
||||
if (current_thd && mutex_obj->m_old_stage_info.count(current_thd) == 0)
|
||||
{
|
||||
my_core::thd_enter_cond(current_thd, &m_cond, mutex_ptr,
|
||||
&stage_waiting_on_row_lock2, &old_stage);
|
||||
if (current_thd && mutex_obj->m_old_stage_info.count(current_thd) == 0) {
|
||||
THD_ENTER_COND(current_thd, &m_cond, mutex_ptr, &stage_waiting_on_row_lock2,
|
||||
&old_stage);
|
||||
/*
|
||||
After the mysql_cond_timedwait we need make this call
|
||||
|
||||
my_core::thd_exit_cond(thd, &old_stage);
|
||||
THD_EXIT_COND(thd, &old_stage);
|
||||
|
||||
to inform the SQL layer that KILLable wait has ended. However,
|
||||
that will cause mutex to be released. Defer the release until the mutex
|
||||
|
@ -105,15 +95,14 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
|||
}
|
||||
|
||||
#endif
|
||||
bool killed= false;
|
||||
bool killed = false;
|
||||
|
||||
do
|
||||
{
|
||||
res= mysql_cond_timedwait(&m_cond, mutex_ptr, &wait_timeout);
|
||||
do {
|
||||
res = mysql_cond_timedwait(&m_cond, mutex_ptr, &wait_timeout);
|
||||
|
||||
#ifndef STANDALONE_UNITTEST
|
||||
if (current_thd)
|
||||
killed= my_core::thd_killed(current_thd);
|
||||
killed = my_core::thd_killed(current_thd);
|
||||
#endif
|
||||
} while (!killed && res == EINTR);
|
||||
|
||||
|
@ -123,7 +112,6 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
|||
return Status::OK();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@note
|
||||
|
@ -154,32 +142,21 @@ Rdb_cond_var::WaitFor(const std::shared_ptr<TransactionDBMutex> mutex_arg,
|
|||
None of this looks like a problem for our use case.
|
||||
*/
|
||||
|
||||
void Rdb_cond_var::Notify()
|
||||
{
|
||||
mysql_cond_signal(&m_cond);
|
||||
}
|
||||
|
||||
void Rdb_cond_var::Notify() { mysql_cond_signal(&m_cond); }
|
||||
|
||||
/*
|
||||
@note
|
||||
This is called without holding the mutex that's used for waiting on the
|
||||
condition. See ::Notify().
|
||||
*/
|
||||
void Rdb_cond_var::NotifyAll()
|
||||
{
|
||||
mysql_cond_broadcast(&m_cond);
|
||||
}
|
||||
void Rdb_cond_var::NotifyAll() { mysql_cond_broadcast(&m_cond); }
|
||||
|
||||
|
||||
Rdb_mutex::Rdb_mutex()
|
||||
{
|
||||
Rdb_mutex::Rdb_mutex() {
|
||||
mysql_mutex_init(0 /* Don't register in P_S. */, &m_mutex,
|
||||
MY_MUTEX_INIT_FAST);
|
||||
}
|
||||
|
||||
Rdb_mutex::~Rdb_mutex() {
|
||||
mysql_mutex_destroy(&m_mutex);
|
||||
}
|
||||
Rdb_mutex::~Rdb_mutex() { mysql_mutex_destroy(&m_mutex); }
|
||||
|
||||
Status Rdb_mutex::Lock() {
|
||||
mysql_mutex_lock(&m_mutex);
|
||||
|
@ -192,8 +169,7 @@ Status Rdb_mutex::Lock() {
|
|||
// If implementing a custom version of this class, the implementation may
|
||||
// choose to ignore the timeout.
|
||||
// Return OK on success, or other Status on failure.
|
||||
Status Rdb_mutex::TryLockFor(int64_t timeout_time __attribute__((__unused__)))
|
||||
{
|
||||
Status Rdb_mutex::TryLockFor(int64_t timeout_time MY_ATTRIBUTE((__unused__))) {
|
||||
/*
|
||||
Note: PThreads API has pthread_mutex_timedlock(), but mysql's
|
||||
mysql_mutex_* wrappers do not wrap that function.
|
||||
|
@ -202,10 +178,8 @@ Status Rdb_mutex::TryLockFor(int64_t timeout_time __attribute__((__unused__)))
|
|||
return Status::OK();
|
||||
}
|
||||
|
||||
|
||||
#ifndef STANDALONE_UNITTEST
|
||||
void Rdb_mutex::set_unlock_action(const PSI_stage_info* const old_stage_arg)
|
||||
{
|
||||
void Rdb_mutex::set_unlock_action(const PSI_stage_info *const old_stage_arg) {
|
||||
DBUG_ASSERT(old_stage_arg != nullptr);
|
||||
|
||||
mysql_mutex_assert_owner(&m_mutex);
|
||||
|
@ -219,17 +193,16 @@ void Rdb_mutex::set_unlock_action(const PSI_stage_info* const old_stage_arg)
|
|||
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
|
||||
void Rdb_mutex::UnLock() {
|
||||
#ifndef STANDALONE_UNITTEST
|
||||
if (m_old_stage_info.count(current_thd) > 0)
|
||||
{
|
||||
if (m_old_stage_info.count(current_thd) > 0) {
|
||||
const std::shared_ptr<PSI_stage_info> old_stage =
|
||||
m_old_stage_info[current_thd];
|
||||
m_old_stage_info[current_thd];
|
||||
m_old_stage_info.erase(current_thd);
|
||||
/* The following will call mysql_mutex_unlock */
|
||||
my_core::thd_exit_cond(current_thd, old_stage.get());
|
||||
THD_EXIT_COND(current_thd, old_stage.get());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
mysql_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -32,10 +32,11 @@
|
|||
|
||||
namespace myrocks {
|
||||
|
||||
class Rdb_mutex: public rocksdb::TransactionDBMutex {
|
||||
Rdb_mutex(const Rdb_mutex& p) = delete;
|
||||
Rdb_mutex& operator = (const Rdb_mutex& p)=delete;
|
||||
public:
|
||||
class Rdb_mutex : public rocksdb::TransactionDBMutex {
|
||||
Rdb_mutex(const Rdb_mutex &p) = delete;
|
||||
Rdb_mutex &operator=(const Rdb_mutex &p) = delete;
|
||||
|
||||
public:
|
||||
Rdb_mutex();
|
||||
virtual ~Rdb_mutex();
|
||||
|
||||
|
@ -53,27 +54,27 @@ class Rdb_mutex: public rocksdb::TransactionDBMutex {
|
|||
// TimedOut if timed out,
|
||||
// or other Status on failure.
|
||||
// If returned status is OK, TransactionDB will eventually call UnLock().
|
||||
virtual rocksdb::Status TryLockFor(
|
||||
int64_t timeout_time __attribute__((__unused__))) override;
|
||||
virtual rocksdb::Status
|
||||
TryLockFor(int64_t timeout_time MY_ATTRIBUTE((__unused__))) override;
|
||||
|
||||
// Unlock Mutex that was successfully locked by Lock() or TryLockUntil()
|
||||
virtual void UnLock() override;
|
||||
|
||||
private:
|
||||
private:
|
||||
mysql_mutex_t m_mutex;
|
||||
friend class Rdb_cond_var;
|
||||
|
||||
#ifndef STANDALONE_UNITTEST
|
||||
void set_unlock_action(const PSI_stage_info* const old_stage_arg);
|
||||
std::unordered_map<THD*, std::shared_ptr<PSI_stage_info>> m_old_stage_info;
|
||||
void set_unlock_action(const PSI_stage_info *const old_stage_arg);
|
||||
std::unordered_map<THD *, std::shared_ptr<PSI_stage_info>> m_old_stage_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
class Rdb_cond_var : public rocksdb::TransactionDBCondVar {
|
||||
Rdb_cond_var(const Rdb_cond_var &) = delete;
|
||||
Rdb_cond_var &operator=(const Rdb_cond_var &) = delete;
|
||||
|
||||
class Rdb_cond_var: public rocksdb::TransactionDBCondVar {
|
||||
Rdb_cond_var(const Rdb_cond_var&) = delete;
|
||||
Rdb_cond_var& operator=(const Rdb_cond_var&) = delete;
|
||||
public:
|
||||
public:
|
||||
Rdb_cond_var();
|
||||
virtual ~Rdb_cond_var();
|
||||
|
||||
|
@ -112,33 +113,30 @@ class Rdb_cond_var: public rocksdb::TransactionDBCondVar {
|
|||
// Unblocks all threads waiting on *this.
|
||||
virtual void NotifyAll() override;
|
||||
|
||||
private:
|
||||
private:
|
||||
mysql_cond_t m_cond;
|
||||
};
|
||||
|
||||
|
||||
class Rdb_mutex_factory : public rocksdb::TransactionDBMutexFactory {
|
||||
public:
|
||||
Rdb_mutex_factory(const Rdb_mutex_factory&) = delete;
|
||||
Rdb_mutex_factory& operator=(const Rdb_mutex_factory&) = delete;
|
||||
public:
|
||||
Rdb_mutex_factory(const Rdb_mutex_factory &) = delete;
|
||||
Rdb_mutex_factory &operator=(const Rdb_mutex_factory &) = delete;
|
||||
Rdb_mutex_factory() {}
|
||||
/*
|
||||
Override parent class's virtual methods of interrest.
|
||||
*/
|
||||
/*
|
||||
Override parent class's virtual methods of interrest.
|
||||
*/
|
||||
|
||||
virtual std::shared_ptr<rocksdb::TransactionDBMutex>
|
||||
AllocateMutex() override {
|
||||
return
|
||||
std::make_shared<Rdb_mutex>();
|
||||
return std::make_shared<Rdb_mutex>();
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<rocksdb::TransactionDBCondVar>
|
||||
AllocateCondVar() override {
|
||||
return
|
||||
std::make_shared<Rdb_cond_var>();
|
||||
return std::make_shared<Rdb_cond_var>();
|
||||
}
|
||||
|
||||
virtual ~Rdb_mutex_factory() {}
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -35,71 +35,68 @@ namespace myrocks {
|
|||
// 2. Update sections (A), (B), and (C) below
|
||||
// 3. Update perf_context.test and show_engine.test
|
||||
|
||||
std::string rdb_pc_stat_types[]=
|
||||
{
|
||||
// (A) These should be in the same order as the PC enum
|
||||
"USER_KEY_COMPARISON_COUNT",
|
||||
"BLOCK_CACHE_HIT_COUNT",
|
||||
"BLOCK_READ_COUNT",
|
||||
"BLOCK_READ_BYTE",
|
||||
"BLOCK_READ_TIME",
|
||||
"BLOCK_CHECKSUM_TIME",
|
||||
"BLOCK_DECOMPRESS_TIME",
|
||||
"INTERNAL_KEY_SKIPPED_COUNT",
|
||||
"INTERNAL_DELETE_SKIPPED_COUNT",
|
||||
"GET_SNAPSHOT_TIME",
|
||||
"GET_FROM_MEMTABLE_TIME",
|
||||
"GET_FROM_MEMTABLE_COUNT",
|
||||
"GET_POST_PROCESS_TIME",
|
||||
"GET_FROM_OUTPUT_FILES_TIME",
|
||||
"SEEK_ON_MEMTABLE_TIME",
|
||||
"SEEK_ON_MEMTABLE_COUNT",
|
||||
"SEEK_CHILD_SEEK_TIME",
|
||||
"SEEK_CHILD_SEEK_COUNT",
|
||||
"SEEK_IN_HEAP_TIME",
|
||||
"SEEK_INTERNAL_SEEK_TIME",
|
||||
"FIND_NEXT_USER_ENTRY_TIME",
|
||||
"WRITE_WAL_TIME",
|
||||
"WRITE_MEMTABLE_TIME",
|
||||
"WRITE_DELAY_TIME",
|
||||
"WRITE_PRE_AND_POST_PROCESS_TIME",
|
||||
"DB_MUTEX_LOCK_NANOS",
|
||||
"DB_CONDITION_WAIT_NANOS",
|
||||
"MERGE_OPERATOR_TIME_NANOS",
|
||||
"READ_INDEX_BLOCK_NANOS",
|
||||
"READ_FILTER_BLOCK_NANOS",
|
||||
"NEW_TABLE_BLOCK_ITER_NANOS",
|
||||
"NEW_TABLE_ITERATOR_NANOS",
|
||||
"BLOCK_SEEK_NANOS",
|
||||
"FIND_TABLE_NANOS",
|
||||
"IO_THREAD_POOL_ID",
|
||||
"IO_BYTES_WRITTEN",
|
||||
"IO_BYTES_READ",
|
||||
"IO_OPEN_NANOS",
|
||||
"IO_ALLOCATE_NANOS",
|
||||
"IO_WRITE_NANOS",
|
||||
"IO_READ_NANOS",
|
||||
"IO_RANGE_SYNC_NANOS",
|
||||
"IO_LOGGER_NANOS"
|
||||
};
|
||||
std::string rdb_pc_stat_types[] = {
|
||||
// (A) These should be in the same order as the PC enum
|
||||
"USER_KEY_COMPARISON_COUNT",
|
||||
"BLOCK_CACHE_HIT_COUNT",
|
||||
"BLOCK_READ_COUNT",
|
||||
"BLOCK_READ_BYTE",
|
||||
"BLOCK_READ_TIME",
|
||||
"BLOCK_CHECKSUM_TIME",
|
||||
"BLOCK_DECOMPRESS_TIME",
|
||||
"INTERNAL_KEY_SKIPPED_COUNT",
|
||||
"INTERNAL_DELETE_SKIPPED_COUNT",
|
||||
"GET_SNAPSHOT_TIME",
|
||||
"GET_FROM_MEMTABLE_TIME",
|
||||
"GET_FROM_MEMTABLE_COUNT",
|
||||
"GET_POST_PROCESS_TIME",
|
||||
"GET_FROM_OUTPUT_FILES_TIME",
|
||||
"SEEK_ON_MEMTABLE_TIME",
|
||||
"SEEK_ON_MEMTABLE_COUNT",
|
||||
"SEEK_CHILD_SEEK_TIME",
|
||||
"SEEK_CHILD_SEEK_COUNT",
|
||||
"SEEK_IN_HEAP_TIME",
|
||||
"SEEK_INTERNAL_SEEK_TIME",
|
||||
"FIND_NEXT_USER_ENTRY_TIME",
|
||||
"WRITE_WAL_TIME",
|
||||
"WRITE_MEMTABLE_TIME",
|
||||
"WRITE_DELAY_TIME",
|
||||
"WRITE_PRE_AND_POST_PROCESS_TIME",
|
||||
"DB_MUTEX_LOCK_NANOS",
|
||||
"DB_CONDITION_WAIT_NANOS",
|
||||
"MERGE_OPERATOR_TIME_NANOS",
|
||||
"READ_INDEX_BLOCK_NANOS",
|
||||
"READ_FILTER_BLOCK_NANOS",
|
||||
"NEW_TABLE_BLOCK_ITER_NANOS",
|
||||
"NEW_TABLE_ITERATOR_NANOS",
|
||||
"BLOCK_SEEK_NANOS",
|
||||
"FIND_TABLE_NANOS",
|
||||
"IO_THREAD_POOL_ID",
|
||||
"IO_BYTES_WRITTEN",
|
||||
"IO_BYTES_READ",
|
||||
"IO_OPEN_NANOS",
|
||||
"IO_ALLOCATE_NANOS",
|
||||
"IO_WRITE_NANOS",
|
||||
"IO_READ_NANOS",
|
||||
"IO_RANGE_SYNC_NANOS",
|
||||
"IO_LOGGER_NANOS"};
|
||||
|
||||
#define IO_PERF_RECORD(_field_) \
|
||||
do { \
|
||||
if (rocksdb::perf_context._field_ > 0) \
|
||||
counters->m_value[idx] += rocksdb::perf_context._field_; \
|
||||
idx++; \
|
||||
#define IO_PERF_RECORD(_field_) \
|
||||
do { \
|
||||
if (rocksdb::perf_context._field_ > 0) \
|
||||
counters->m_value[idx] += rocksdb::perf_context._field_; \
|
||||
idx++; \
|
||||
} while (0)
|
||||
#define IO_STAT_RECORD(_field_) \
|
||||
do { \
|
||||
if (rocksdb::iostats_context._field_ > 0) \
|
||||
counters->m_value[idx] += rocksdb::iostats_context._field_; \
|
||||
idx++; \
|
||||
#define IO_STAT_RECORD(_field_) \
|
||||
do { \
|
||||
if (rocksdb::iostats_context._field_ > 0) \
|
||||
counters->m_value[idx] += rocksdb::iostats_context._field_; \
|
||||
idx++; \
|
||||
} while (0)
|
||||
|
||||
static void harvest_diffs(Rdb_atomic_perf_counters * const counters)
|
||||
{
|
||||
static void harvest_diffs(Rdb_atomic_perf_counters *const counters) {
|
||||
// (C) These should be in the same order as the PC enum
|
||||
size_t idx= 0;
|
||||
size_t idx = 0;
|
||||
IO_PERF_RECORD(user_key_comparison_count);
|
||||
IO_PERF_RECORD(block_cache_hit_count);
|
||||
IO_PERF_RECORD(block_read_count);
|
||||
|
@ -148,35 +145,29 @@ static void harvest_diffs(Rdb_atomic_perf_counters * const counters)
|
|||
#undef IO_PERF_DIFF
|
||||
#undef IO_STAT_DIFF
|
||||
|
||||
|
||||
static Rdb_atomic_perf_counters rdb_global_perf_counters;
|
||||
|
||||
void rdb_get_global_perf_counters(Rdb_perf_counters* const counters)
|
||||
{
|
||||
void rdb_get_global_perf_counters(Rdb_perf_counters *const counters) {
|
||||
DBUG_ASSERT(counters != nullptr);
|
||||
|
||||
counters->load(rdb_global_perf_counters);
|
||||
}
|
||||
|
||||
void Rdb_perf_counters::load(const Rdb_atomic_perf_counters &atomic_counters)
|
||||
{
|
||||
for (int i= 0; i < PC_MAX_IDX; i++) {
|
||||
m_value[i]= atomic_counters.m_value[i].load(std::memory_order_relaxed);
|
||||
void Rdb_perf_counters::load(const Rdb_atomic_perf_counters &atomic_counters) {
|
||||
for (int i = 0; i < PC_MAX_IDX; i++) {
|
||||
m_value[i] = atomic_counters.m_value[i].load(std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
bool Rdb_io_perf::start(const uint32_t perf_context_level)
|
||||
{
|
||||
const rocksdb::PerfLevel perf_level=
|
||||
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
||||
bool Rdb_io_perf::start(const uint32_t perf_context_level) {
|
||||
const rocksdb::PerfLevel perf_level =
|
||||
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
||||
|
||||
if (rocksdb::GetPerfLevel() != perf_level)
|
||||
{
|
||||
if (rocksdb::GetPerfLevel() != perf_level) {
|
||||
rocksdb::SetPerfLevel(perf_level);
|
||||
}
|
||||
|
||||
if (perf_level == rocksdb::kDisable)
|
||||
{
|
||||
if (perf_level == rocksdb::kDisable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -185,38 +176,33 @@ bool Rdb_io_perf::start(const uint32_t perf_context_level)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Rdb_io_perf::end_and_record(const uint32_t perf_context_level)
|
||||
{
|
||||
const rocksdb::PerfLevel perf_level=
|
||||
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
||||
void Rdb_io_perf::end_and_record(const uint32_t perf_context_level) {
|
||||
const rocksdb::PerfLevel perf_level =
|
||||
static_cast<rocksdb::PerfLevel>(perf_context_level);
|
||||
|
||||
if (perf_level == rocksdb::kDisable)
|
||||
{
|
||||
if (perf_level == rocksdb::kDisable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_atomic_counters)
|
||||
{
|
||||
if (m_atomic_counters) {
|
||||
harvest_diffs(m_atomic_counters);
|
||||
}
|
||||
harvest_diffs(&rdb_global_perf_counters);
|
||||
|
||||
if (m_shared_io_perf_read &&
|
||||
(rocksdb::perf_context.block_read_byte != 0 ||
|
||||
rocksdb::perf_context.block_read_count != 0 ||
|
||||
rocksdb::perf_context.block_read_time != 0))
|
||||
{
|
||||
if (m_shared_io_perf_read && (rocksdb::perf_context.block_read_byte != 0 ||
|
||||
rocksdb::perf_context.block_read_count != 0 ||
|
||||
rocksdb::perf_context.block_read_time != 0)) {
|
||||
my_io_perf_t io_perf_read;
|
||||
|
||||
io_perf_read.init();
|
||||
io_perf_read.bytes= rocksdb::perf_context.block_read_byte;
|
||||
io_perf_read.requests= rocksdb::perf_context.block_read_count;
|
||||
io_perf_read.bytes = rocksdb::perf_context.block_read_byte;
|
||||
io_perf_read.requests = rocksdb::perf_context.block_read_count;
|
||||
|
||||
/*
|
||||
Rocksdb does not distinguish between I/O service and wait time, so just
|
||||
use svc time.
|
||||
*/
|
||||
io_perf_read.svc_time_max= io_perf_read.svc_time=
|
||||
io_perf_read.svc_time_max = io_perf_read.svc_time =
|
||||
rocksdb::perf_context.block_read_time;
|
||||
|
||||
m_shared_io_perf_read->sum(io_perf_read);
|
||||
|
@ -224,17 +210,15 @@ void Rdb_io_perf::end_and_record(const uint32_t perf_context_level)
|
|||
}
|
||||
|
||||
if (m_stats) {
|
||||
if (rocksdb::perf_context.internal_key_skipped_count != 0)
|
||||
{
|
||||
if (rocksdb::perf_context.internal_key_skipped_count != 0) {
|
||||
m_stats->key_skipped += rocksdb::perf_context.internal_key_skipped_count;
|
||||
}
|
||||
|
||||
if (rocksdb::perf_context.internal_delete_skipped_count != 0)
|
||||
{
|
||||
if (rocksdb::perf_context.internal_delete_skipped_count != 0) {
|
||||
m_stats->delete_skipped +=
|
||||
rocksdb::perf_context.internal_delete_skipped_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -80,8 +80,7 @@ class Rdb_perf_counters;
|
|||
A collection of performance counters that can be safely incremented by
|
||||
multiple threads since it stores atomic datapoints.
|
||||
*/
|
||||
struct Rdb_atomic_perf_counters
|
||||
{
|
||||
struct Rdb_atomic_perf_counters {
|
||||
std::atomic_ullong m_value[PC_MAX_IDX];
|
||||
};
|
||||
|
||||
|
@ -89,11 +88,11 @@ struct Rdb_atomic_perf_counters
|
|||
A collection of performance counters that is meant to be incremented by
|
||||
a single thread.
|
||||
*/
|
||||
class Rdb_perf_counters
|
||||
{
|
||||
Rdb_perf_counters(const Rdb_perf_counters&) = delete;
|
||||
Rdb_perf_counters& operator=(const Rdb_perf_counters&) = delete;
|
||||
public:
|
||||
class Rdb_perf_counters {
|
||||
Rdb_perf_counters(const Rdb_perf_counters &) = delete;
|
||||
Rdb_perf_counters &operator=(const Rdb_perf_counters &) = delete;
|
||||
|
||||
public:
|
||||
Rdb_perf_counters() = default;
|
||||
uint64_t m_value[PC_MAX_IDX];
|
||||
|
||||
|
@ -105,36 +104,34 @@ extern std::string rdb_pc_stat_types[PC_MAX_IDX];
|
|||
/*
|
||||
Perf timers for data reads
|
||||
*/
|
||||
class Rdb_io_perf
|
||||
{
|
||||
class Rdb_io_perf {
|
||||
// Context management
|
||||
Rdb_atomic_perf_counters *m_atomic_counters= nullptr;
|
||||
my_io_perf_atomic_t *m_shared_io_perf_read= nullptr;
|
||||
ha_statistics *m_stats= nullptr;
|
||||
Rdb_atomic_perf_counters *m_atomic_counters = nullptr;
|
||||
my_io_perf_atomic_t *m_shared_io_perf_read = nullptr;
|
||||
ha_statistics *m_stats = nullptr;
|
||||
|
||||
public:
|
||||
Rdb_io_perf(const Rdb_io_perf&) = delete;
|
||||
Rdb_io_perf& operator=(const Rdb_io_perf&) = delete;
|
||||
public:
|
||||
Rdb_io_perf(const Rdb_io_perf &) = delete;
|
||||
Rdb_io_perf &operator=(const Rdb_io_perf &) = delete;
|
||||
|
||||
void init(Rdb_atomic_perf_counters* const atomic_counters,
|
||||
my_io_perf_atomic_t* const shared_io_perf_read,
|
||||
ha_statistics* const stats)
|
||||
{
|
||||
void init(Rdb_atomic_perf_counters *const atomic_counters,
|
||||
my_io_perf_atomic_t *const shared_io_perf_read,
|
||||
ha_statistics *const stats) {
|
||||
DBUG_ASSERT(atomic_counters != nullptr);
|
||||
DBUG_ASSERT(shared_io_perf_read != nullptr);
|
||||
DBUG_ASSERT(stats != nullptr);
|
||||
|
||||
m_atomic_counters= atomic_counters;
|
||||
m_shared_io_perf_read= shared_io_perf_read;
|
||||
m_stats= stats;
|
||||
m_atomic_counters = atomic_counters;
|
||||
m_shared_io_perf_read = shared_io_perf_read;
|
||||
m_stats = stats;
|
||||
}
|
||||
|
||||
bool start(const uint32_t perf_context_level);
|
||||
void end_and_record(const uint32_t perf_context_level);
|
||||
|
||||
explicit Rdb_io_perf() : m_atomic_counters(nullptr),
|
||||
m_shared_io_perf_read(nullptr),
|
||||
m_stats(nullptr) {}
|
||||
explicit Rdb_io_perf()
|
||||
: m_atomic_counters(nullptr), m_shared_io_perf_read(nullptr),
|
||||
m_stats(nullptr) {}
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -37,26 +37,20 @@
|
|||
|
||||
namespace myrocks {
|
||||
|
||||
Rdb_sst_file::Rdb_sst_file(rocksdb::DB* const db,
|
||||
rocksdb::ColumnFamilyHandle* const cf,
|
||||
const rocksdb::DBOptions& db_options,
|
||||
const std::string& name, const bool tracing) :
|
||||
m_db(db),
|
||||
m_cf(cf),
|
||||
m_db_options(db_options),
|
||||
m_sst_file_writer(nullptr),
|
||||
m_name(name),
|
||||
m_tracing(tracing)
|
||||
{
|
||||
Rdb_sst_file::Rdb_sst_file(rocksdb::DB *const db,
|
||||
rocksdb::ColumnFamilyHandle *const cf,
|
||||
const rocksdb::DBOptions &db_options,
|
||||
const std::string &name, const bool tracing)
|
||||
: m_db(db), m_cf(cf), m_db_options(db_options), m_sst_file_writer(nullptr),
|
||||
m_name(name), m_tracing(tracing) {
|
||||
DBUG_ASSERT(db != nullptr);
|
||||
DBUG_ASSERT(cf != nullptr);
|
||||
}
|
||||
|
||||
Rdb_sst_file::~Rdb_sst_file()
|
||||
{
|
||||
Rdb_sst_file::~Rdb_sst_file() {
|
||||
// Make sure we clean up
|
||||
delete m_sst_file_writer;
|
||||
m_sst_file_writer= nullptr;
|
||||
m_sst_file_writer = nullptr;
|
||||
|
||||
// In case something went wrong attempt to delete the temporary file.
|
||||
// If everything went fine that file will have been renamed and this
|
||||
|
@ -64,98 +58,86 @@ Rdb_sst_file::~Rdb_sst_file()
|
|||
std::remove(m_name.c_str());
|
||||
}
|
||||
|
||||
rocksdb::Status Rdb_sst_file::open()
|
||||
{
|
||||
rocksdb::Status Rdb_sst_file::open() {
|
||||
DBUG_ASSERT(m_sst_file_writer == nullptr);
|
||||
|
||||
rocksdb::ColumnFamilyDescriptor cf_descr;
|
||||
|
||||
rocksdb::Status s= m_cf->GetDescriptor(&cf_descr);
|
||||
if (!s.ok())
|
||||
{
|
||||
rocksdb::Status s = m_cf->GetDescriptor(&cf_descr);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// Create an sst file writer with the current options and comparator
|
||||
const rocksdb::Comparator* comparator= m_cf->GetComparator();
|
||||
const rocksdb::Comparator *comparator = m_cf->GetComparator();
|
||||
|
||||
const rocksdb::EnvOptions env_options(m_db_options);
|
||||
const rocksdb::Options options(m_db_options, cf_descr.options);
|
||||
|
||||
m_sst_file_writer=
|
||||
m_sst_file_writer =
|
||||
new rocksdb::SstFileWriter(env_options, options, comparator, m_cf);
|
||||
|
||||
s= m_sst_file_writer->Open(m_name);
|
||||
if (m_tracing)
|
||||
{
|
||||
s = m_sst_file_writer->Open(m_name);
|
||||
if (m_tracing) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_information("SST Tracing: Open(%s) returned %s", m_name.c_str(),
|
||||
s.ok() ? "ok" : "not ok");
|
||||
}
|
||||
|
||||
if (!s.ok())
|
||||
{
|
||||
if (!s.ok()) {
|
||||
delete m_sst_file_writer;
|
||||
m_sst_file_writer= nullptr;
|
||||
m_sst_file_writer = nullptr;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
rocksdb::Status Rdb_sst_file::put(const rocksdb::Slice& key,
|
||||
const rocksdb::Slice& value)
|
||||
{
|
||||
rocksdb::Status Rdb_sst_file::put(const rocksdb::Slice &key,
|
||||
const rocksdb::Slice &value) {
|
||||
DBUG_ASSERT(m_sst_file_writer != nullptr);
|
||||
|
||||
// Add the specified key/value to the sst file writer
|
||||
return m_sst_file_writer->Add(key, value);
|
||||
}
|
||||
|
||||
std::string Rdb_sst_file::generateKey(const std::string& key)
|
||||
{
|
||||
static char const hexdigit[]= {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
std::string Rdb_sst_file::generateKey(const std::string &key) {
|
||||
static char const hexdigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
std::string res;
|
||||
|
||||
res.reserve(key.size() * 2);
|
||||
|
||||
for (auto ch : key)
|
||||
{
|
||||
res += hexdigit[((uint8_t) ch) >> 4];
|
||||
res += hexdigit[((uint8_t) ch) & 0x0F];
|
||||
for (auto ch : key) {
|
||||
res += hexdigit[((uint8_t)ch) >> 4];
|
||||
res += hexdigit[((uint8_t)ch) & 0x0F];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// This function is run by the background thread
|
||||
rocksdb::Status Rdb_sst_file::commit()
|
||||
{
|
||||
rocksdb::Status Rdb_sst_file::commit() {
|
||||
DBUG_ASSERT(m_sst_file_writer != nullptr);
|
||||
|
||||
rocksdb::Status s;
|
||||
rocksdb::ExternalSstFileInfo fileinfo; ///Finish may should be modified
|
||||
rocksdb::ExternalSstFileInfo fileinfo; /// Finish may should be modified
|
||||
|
||||
// Close out the sst file
|
||||
s= m_sst_file_writer->Finish(&fileinfo);
|
||||
if (m_tracing)
|
||||
{
|
||||
s = m_sst_file_writer->Finish(&fileinfo);
|
||||
if (m_tracing) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_information("SST Tracing: Finish returned %s",
|
||||
s.ok() ? "ok" : "not ok");
|
||||
}
|
||||
|
||||
if (s.ok())
|
||||
{
|
||||
if (m_tracing)
|
||||
{
|
||||
if (s.ok()) {
|
||||
if (m_tracing) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_information("SST Tracing: Adding file %s, smallest key: %s, "
|
||||
"largest key: %s, file size: %" PRIu64 ", "
|
||||
"num_entries: %" PRIu64, fileinfo.file_path.c_str(),
|
||||
"num_entries: %" PRIu64,
|
||||
fileinfo.file_path.c_str(),
|
||||
generateKey(fileinfo.smallest_key).c_str(),
|
||||
generateKey(fileinfo.largest_key).c_str(),
|
||||
fileinfo.file_size, fileinfo.num_entries);
|
||||
|
@ -169,10 +151,9 @@ rocksdb::Status Rdb_sst_file::commit()
|
|||
opts.snapshot_consistency = false;
|
||||
opts.allow_global_seqno = 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
|
||||
sql_print_information("SST Tracing: AddFile(%s) returned %s",
|
||||
fileinfo.file_path.c_str(),
|
||||
|
@ -181,106 +162,84 @@ rocksdb::Status Rdb_sst_file::commit()
|
|||
}
|
||||
|
||||
delete m_sst_file_writer;
|
||||
m_sst_file_writer= nullptr;
|
||||
m_sst_file_writer = nullptr;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
Rdb_sst_info::Rdb_sst_info(rocksdb::DB* const db, const std::string& tablename,
|
||||
const std::string& indexname,
|
||||
rocksdb::ColumnFamilyHandle* const cf,
|
||||
const rocksdb::DBOptions& db_options,
|
||||
const bool& tracing) :
|
||||
m_db(db),
|
||||
m_cf(cf),
|
||||
m_db_options(db_options),
|
||||
m_curr_size(0),
|
||||
m_sst_count(0),
|
||||
m_error_msg(""),
|
||||
Rdb_sst_info::Rdb_sst_info(rocksdb::DB *const db, const std::string &tablename,
|
||||
const std::string &indexname,
|
||||
rocksdb::ColumnFamilyHandle *const cf,
|
||||
const rocksdb::DBOptions &db_options,
|
||||
const bool &tracing)
|
||||
: m_db(db), m_cf(cf), m_db_options(db_options), m_curr_size(0),
|
||||
m_sst_count(0), m_error_msg(""),
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
m_queue(),
|
||||
m_mutex(),
|
||||
m_cond(),
|
||||
m_thread(nullptr),
|
||||
m_finished(false),
|
||||
m_queue(), m_mutex(), m_cond(), m_thread(nullptr), m_finished(false),
|
||||
#endif
|
||||
m_sst_file(nullptr),
|
||||
m_tracing(tracing)
|
||||
{
|
||||
m_prefix= db->GetName() + "/";
|
||||
m_sst_file(nullptr), m_tracing(tracing) {
|
||||
m_prefix = db->GetName() + "/";
|
||||
|
||||
std::string normalized_table;
|
||||
if (rdb_normalize_tablename(tablename.c_str(), &normalized_table))
|
||||
{
|
||||
if (rdb_normalize_tablename(tablename.c_str(), &normalized_table)) {
|
||||
// We failed to get a normalized table name. This should never happen,
|
||||
// but handle it anyway.
|
||||
m_prefix += "fallback_" +
|
||||
std::to_string(
|
||||
reinterpret_cast<intptr_t>(reinterpret_cast<void*>(this))) + "_" +
|
||||
indexname + "_";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefix += "fallback_" + std::to_string(reinterpret_cast<intptr_t>(
|
||||
reinterpret_cast<void *>(this))) +
|
||||
"_" + indexname + "_";
|
||||
} else {
|
||||
m_prefix += normalized_table + "_" + indexname + "_";
|
||||
}
|
||||
|
||||
rocksdb::ColumnFamilyDescriptor cf_descr;
|
||||
const rocksdb::Status s= m_cf->GetDescriptor(&cf_descr);
|
||||
if (!s.ok())
|
||||
{
|
||||
const rocksdb::Status s = m_cf->GetDescriptor(&cf_descr);
|
||||
if (!s.ok()) {
|
||||
// Default size if we can't get the cf's target size
|
||||
m_max_size= 64*1024*1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_max_size = 64 * 1024 * 1024;
|
||||
} else {
|
||||
// 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);
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
DBUG_ASSERT(m_thread == nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Rdb_sst_info::open_new_sst_file()
|
||||
{
|
||||
int Rdb_sst_info::open_new_sst_file() {
|
||||
DBUG_ASSERT(m_sst_file == nullptr);
|
||||
|
||||
// Create the new sst file's name
|
||||
const std::string name= m_prefix + std::to_string(m_sst_count++) + m_suffix;
|
||||
const std::string name = m_prefix + std::to_string(m_sst_count++) + m_suffix;
|
||||
|
||||
// Create the new sst file object
|
||||
m_sst_file= new Rdb_sst_file(m_db, m_cf, m_db_options, name, m_tracing);
|
||||
m_sst_file = new Rdb_sst_file(m_db, m_cf, m_db_options, name, m_tracing);
|
||||
|
||||
// Open the sst file
|
||||
const rocksdb::Status s= m_sst_file->open();
|
||||
if (!s.ok())
|
||||
{
|
||||
const rocksdb::Status s = m_sst_file->open();
|
||||
if (!s.ok()) {
|
||||
set_error_msg(s.ToString());
|
||||
delete m_sst_file;
|
||||
m_sst_file= nullptr;
|
||||
return 1;
|
||||
m_sst_file = nullptr;
|
||||
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_curr_size > 0);
|
||||
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
if (m_thread == nullptr)
|
||||
{
|
||||
if (m_thread == nullptr) {
|
||||
// We haven't already started a background thread, so start one
|
||||
m_thread= new std::thread(thread_fcn, this);
|
||||
m_thread = new std::thread(thread_fcn, this);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(m_thread != nullptr);
|
||||
|
@ -294,9 +253,8 @@ void Rdb_sst_info::close_curr_sst_file()
|
|||
// Notify the background thread that there is a new entry in the queue
|
||||
m_cond.notify_one();
|
||||
#else
|
||||
const rocksdb::Status s= m_sst_file->commit();
|
||||
if (!s.ok())
|
||||
{
|
||||
const rocksdb::Status s = m_sst_file->commit();
|
||||
if (!s.ok()) {
|
||||
set_error_msg(s.ToString());
|
||||
}
|
||||
|
||||
|
@ -304,34 +262,28 @@ void Rdb_sst_info::close_curr_sst_file()
|
|||
#endif
|
||||
|
||||
// Reset for next sst file
|
||||
m_sst_file= nullptr;
|
||||
m_curr_size= 0;
|
||||
m_sst_file = nullptr;
|
||||
m_curr_size = 0;
|
||||
}
|
||||
|
||||
int Rdb_sst_info::put(const rocksdb::Slice& key,
|
||||
const rocksdb::Slice& value)
|
||||
{
|
||||
int Rdb_sst_info::put(const rocksdb::Slice &key, const rocksdb::Slice &value) {
|
||||
int rc;
|
||||
|
||||
if (m_curr_size >= m_max_size)
|
||||
{
|
||||
if (m_curr_size >= m_max_size) {
|
||||
// The current sst file has reached its maximum, close it out
|
||||
close_curr_sst_file();
|
||||
|
||||
// While we are here, check to see if we have had any errors from the
|
||||
// background thread - we don't want to wait for the end to report them
|
||||
if (!m_error_msg.empty())
|
||||
{
|
||||
return 1;
|
||||
if (!m_error_msg.empty()) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_curr_size == 0)
|
||||
{
|
||||
if (m_curr_size == 0) {
|
||||
// We don't have an sst file open - open one
|
||||
rc= open_new_sst_file();
|
||||
if (rc != 0)
|
||||
{
|
||||
rc = open_new_sst_file();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
@ -339,51 +291,45 @@ int Rdb_sst_info::put(const rocksdb::Slice& key,
|
|||
DBUG_ASSERT(m_sst_file != nullptr);
|
||||
|
||||
// Add the key/value to the current sst file
|
||||
const rocksdb::Status s= m_sst_file->put(key, value);
|
||||
if (!s.ok())
|
||||
{
|
||||
const rocksdb::Status s = m_sst_file->put(key, value);
|
||||
if (!s.ok()) {
|
||||
set_error_msg(s.ToString());
|
||||
return 1;
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
m_curr_size += key.size() + value.size();
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int Rdb_sst_info::commit()
|
||||
{
|
||||
if (m_curr_size > 0)
|
||||
{
|
||||
int Rdb_sst_info::commit() {
|
||||
if (m_curr_size > 0) {
|
||||
// Close out any existing files
|
||||
close_curr_sst_file();
|
||||
}
|
||||
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
if (m_thread != nullptr)
|
||||
{
|
||||
if (m_thread != nullptr) {
|
||||
// Tell the background thread we are done
|
||||
m_finished= true;
|
||||
m_finished = true;
|
||||
m_cond.notify_one();
|
||||
|
||||
// Wait for the background thread to finish
|
||||
m_thread->join();
|
||||
delete m_thread;
|
||||
m_thread= nullptr;
|
||||
m_thread = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Did we get any errors?
|
||||
if (!m_error_msg.empty())
|
||||
{
|
||||
return 1;
|
||||
if (!m_error_msg.empty()) {
|
||||
return HA_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return HA_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void Rdb_sst_info::set_error_msg(const std::string& msg)
|
||||
{
|
||||
void Rdb_sst_info::set_error_msg(const std::string &msg) {
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
// Both the foreground and background threads can set the error message
|
||||
// so lock the mutex to protect it. We only want the first error that
|
||||
|
@ -391,41 +337,35 @@ void Rdb_sst_info::set_error_msg(const std::string& msg)
|
|||
const std::lock_guard<std::mutex> guard(m_mutex);
|
||||
#endif
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "bulk load error: %s", MYF(0), msg.c_str());
|
||||
if (m_error_msg.empty())
|
||||
{
|
||||
m_error_msg= msg;
|
||||
if (m_error_msg.empty()) {
|
||||
m_error_msg = msg;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
// Static thread function - the Rdb_sst_info object is in 'object'
|
||||
void Rdb_sst_info::thread_fcn(void* object)
|
||||
{
|
||||
reinterpret_cast<Rdb_sst_info*>(object)->run_thread();
|
||||
void Rdb_sst_info::thread_fcn(void *object) {
|
||||
reinterpret_cast<Rdb_sst_info *>(object)->run_thread();
|
||||
}
|
||||
|
||||
void Rdb_sst_info::run_thread()
|
||||
{
|
||||
void Rdb_sst_info::run_thread() {
|
||||
const std::unique_lock<std::mutex> lk(m_mutex);
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
// Wait for notification or 1 second to pass
|
||||
m_cond.wait_for(lk, std::chrono::seconds(1));
|
||||
|
||||
// Inner loop pulls off all Rdb_sst_file entries and processes them
|
||||
while (!m_queue.empty())
|
||||
{
|
||||
const Rdb_sst_file* const sst_file= m_queue.front();
|
||||
while (!m_queue.empty()) {
|
||||
const Rdb_sst_file *const sst_file = m_queue.front();
|
||||
m_queue.pop();
|
||||
|
||||
// Release the lock - we don't want to hold it while committing the file
|
||||
lk.unlock();
|
||||
|
||||
// Close out the sst file and add it to the database
|
||||
const rocksdb::Status s= sst_file->commit();
|
||||
if (!s.ok())
|
||||
{
|
||||
const rocksdb::Status s = sst_file->commit();
|
||||
if (!s.ok()) {
|
||||
set_error_msg(s.ToString());
|
||||
}
|
||||
|
||||
|
@ -443,14 +383,12 @@ void Rdb_sst_info::run_thread()
|
|||
}
|
||||
#endif
|
||||
|
||||
void Rdb_sst_info::init(const rocksdb::DB* const db)
|
||||
{
|
||||
const std::string path= db->GetName() + FN_DIRSEP;
|
||||
struct st_my_dir* const dir_info= my_dir(path.c_str(), MYF(MY_DONT_SORT));
|
||||
void Rdb_sst_info::init(const rocksdb::DB *const db) {
|
||||
const std::string path = db->GetName() + FN_DIRSEP;
|
||||
struct st_my_dir *const dir_info = my_dir(path.c_str(), MYF(MY_DONT_SORT));
|
||||
|
||||
// Access the directory
|
||||
if (dir_info == nullptr)
|
||||
{
|
||||
if (dir_info == nullptr) {
|
||||
// NO_LINT_DEBUG
|
||||
sql_print_warning("RocksDB: Could not access database directory: %s",
|
||||
path.c_str());
|
||||
|
@ -458,16 +396,14 @@ void Rdb_sst_info::init(const rocksdb::DB* const db)
|
|||
}
|
||||
|
||||
// Scan through the files in the directory
|
||||
const struct fileinfo* file_info= dir_info->dir_entry;
|
||||
for (uint ii= 0; ii < dir_info->number_off_files; ii++, file_info++)
|
||||
{
|
||||
const struct fileinfo *file_info = dir_info->dir_entry;
|
||||
for (uint ii = 0; ii < dir_info->number_off_files; ii++, file_info++) {
|
||||
// find any files ending with m_suffix ...
|
||||
const std::string name= file_info->name;
|
||||
const size_t pos= name.find(m_suffix);
|
||||
if (pos != std::string::npos && name.size() - pos == m_suffix.size())
|
||||
{
|
||||
const std::string name = file_info->name;
|
||||
const size_t pos = name.find(m_suffix);
|
||||
if (pos != std::string::npos && name.size() - pos == m_suffix.size()) {
|
||||
// ... and remove them
|
||||
const std::string fullname= path + name;
|
||||
const std::string fullname = path + name;
|
||||
my_delete(fullname.c_str(), MYF(0));
|
||||
}
|
||||
}
|
||||
|
@ -476,5 +412,5 @@ void Rdb_sst_info::init(const rocksdb::DB* const db)
|
|||
my_dirend(dir_info);
|
||||
}
|
||||
|
||||
std::string Rdb_sst_info::m_suffix= ".bulk_load.tmp";
|
||||
} // namespace myrocks
|
||||
std::string Rdb_sst_info::m_suffix = ".bulk_load.tmp";
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -33,78 +33,77 @@
|
|||
namespace myrocks {
|
||||
|
||||
class Rdb_sst_file {
|
||||
private:
|
||||
Rdb_sst_file(const Rdb_sst_file& p)= delete;
|
||||
Rdb_sst_file& operator=(const Rdb_sst_file& p)= delete;
|
||||
private:
|
||||
Rdb_sst_file(const Rdb_sst_file &p) = delete;
|
||||
Rdb_sst_file &operator=(const Rdb_sst_file &p) = delete;
|
||||
|
||||
rocksdb::DB* const m_db;
|
||||
rocksdb::ColumnFamilyHandle* const m_cf;
|
||||
const rocksdb::DBOptions& m_db_options;
|
||||
rocksdb::SstFileWriter* m_sst_file_writer;
|
||||
const std::string m_name;
|
||||
const bool m_tracing;
|
||||
rocksdb::DB *const m_db;
|
||||
rocksdb::ColumnFamilyHandle *const m_cf;
|
||||
const rocksdb::DBOptions &m_db_options;
|
||||
rocksdb::SstFileWriter *m_sst_file_writer;
|
||||
const std::string m_name;
|
||||
const bool m_tracing;
|
||||
|
||||
std::string generateKey(const std::string& key);
|
||||
std::string generateKey(const std::string &key);
|
||||
|
||||
public:
|
||||
Rdb_sst_file(rocksdb::DB* const db,
|
||||
rocksdb::ColumnFamilyHandle* const cf,
|
||||
const rocksdb::DBOptions& db_options, const std::string& name,
|
||||
public:
|
||||
Rdb_sst_file(rocksdb::DB *const db, rocksdb::ColumnFamilyHandle *const cf,
|
||||
const rocksdb::DBOptions &db_options, const std::string &name,
|
||||
const bool tracing);
|
||||
~Rdb_sst_file();
|
||||
|
||||
rocksdb::Status open();
|
||||
rocksdb::Status put(const rocksdb::Slice& key, const rocksdb::Slice& value);
|
||||
rocksdb::Status put(const rocksdb::Slice &key, const rocksdb::Slice &value);
|
||||
rocksdb::Status commit();
|
||||
};
|
||||
|
||||
class Rdb_sst_info {
|
||||
private:
|
||||
Rdb_sst_info(const Rdb_sst_info& p)= delete;
|
||||
Rdb_sst_info& operator=(const Rdb_sst_info& p)= delete;
|
||||
private:
|
||||
Rdb_sst_info(const Rdb_sst_info &p) = delete;
|
||||
Rdb_sst_info &operator=(const Rdb_sst_info &p) = delete;
|
||||
|
||||
rocksdb::DB* const m_db;
|
||||
rocksdb::ColumnFamilyHandle* const m_cf;
|
||||
const rocksdb::DBOptions& m_db_options;
|
||||
uint64_t m_curr_size;
|
||||
uint64_t m_max_size;
|
||||
uint m_sst_count;
|
||||
std::string m_error_msg;
|
||||
std::string m_prefix;
|
||||
static std::string m_suffix;
|
||||
rocksdb::DB *const m_db;
|
||||
rocksdb::ColumnFamilyHandle *const m_cf;
|
||||
const rocksdb::DBOptions &m_db_options;
|
||||
uint64_t m_curr_size;
|
||||
uint64_t m_max_size;
|
||||
uint m_sst_count;
|
||||
std::string m_error_msg;
|
||||
std::string m_prefix;
|
||||
static std::string m_suffix;
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
std::queue<Rdb_sst_file*> m_queue;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cond;
|
||||
std::thread* m_thread;
|
||||
bool m_finished;
|
||||
std::queue<Rdb_sst_file *> m_queue;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cond;
|
||||
std::thread *m_thread;
|
||||
bool m_finished;
|
||||
#endif
|
||||
Rdb_sst_file* m_sst_file;
|
||||
const bool m_tracing;
|
||||
Rdb_sst_file *m_sst_file;
|
||||
const bool m_tracing;
|
||||
|
||||
int open_new_sst_file();
|
||||
void close_curr_sst_file();
|
||||
void set_error_msg(const std::string& msg);
|
||||
void set_error_msg(const std::string &msg);
|
||||
|
||||
#if defined(RDB_SST_INFO_USE_THREAD)
|
||||
void run_thread();
|
||||
|
||||
static void thread_fcn(void* object);
|
||||
static void thread_fcn(void *object);
|
||||
#endif
|
||||
|
||||
public:
|
||||
Rdb_sst_info(rocksdb::DB* const db, const std::string& tablename,
|
||||
const std::string& indexname,
|
||||
rocksdb::ColumnFamilyHandle* const cf,
|
||||
const rocksdb::DBOptions& db_options, const bool &tracing);
|
||||
public:
|
||||
Rdb_sst_info(rocksdb::DB *const db, const std::string &tablename,
|
||||
const std::string &indexname,
|
||||
rocksdb::ColumnFamilyHandle *const cf,
|
||||
const rocksdb::DBOptions &db_options, const bool &tracing);
|
||||
~Rdb_sst_info();
|
||||
|
||||
int put(const rocksdb::Slice& key, const rocksdb::Slice& value);
|
||||
int put(const rocksdb::Slice &key, const rocksdb::Slice &value);
|
||||
int commit();
|
||||
|
||||
const std::string& error_message() const { return m_error_msg; }
|
||||
const std::string &error_message() const { return m_error_msg; }
|
||||
|
||||
static void init(const rocksdb::DB* const db);
|
||||
static void init(const rocksdb::DB *const db);
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
/* The C++ file's header */
|
||||
|
@ -24,58 +24,64 @@
|
|||
|
||||
namespace myrocks {
|
||||
|
||||
void* Rdb_thread::thread_func(void* const thread_ptr)
|
||||
{
|
||||
void *Rdb_thread::thread_func(void *const thread_ptr) {
|
||||
DBUG_ASSERT(thread_ptr != nullptr);
|
||||
Rdb_thread* const thread= static_cast<Rdb_thread* const>(thread_ptr);
|
||||
if (!thread->m_run_once.exchange(true))
|
||||
{
|
||||
Rdb_thread *const thread = static_cast<Rdb_thread *const>(thread_ptr);
|
||||
if (!thread->m_run_once.exchange(true)) {
|
||||
thread->run();
|
||||
thread->uninit();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void Rdb_thread::init(
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
||||
my_core::PSI_cond_key stop_bg_psi_cond_key
|
||||
my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
||||
my_core::PSI_cond_key stop_bg_psi_cond_key
|
||||
#endif
|
||||
)
|
||||
{
|
||||
) {
|
||||
DBUG_ASSERT(!m_run_once);
|
||||
mysql_mutex_init(stop_bg_psi_mutex_key, &m_signal_mutex, MY_MUTEX_INIT_FAST);
|
||||
mysql_cond_init(stop_bg_psi_cond_key, &m_signal_cond, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void Rdb_thread::uninit()
|
||||
{
|
||||
void Rdb_thread::uninit() {
|
||||
mysql_mutex_destroy(&m_signal_mutex);
|
||||
mysql_cond_destroy(&m_signal_cond);
|
||||
}
|
||||
|
||||
|
||||
int Rdb_thread::create_thread(
|
||||
int Rdb_thread::create_thread(const std::string &thread_name
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
PSI_thread_key background_psi_thread_key
|
||||
,
|
||||
PSI_thread_key background_psi_thread_key
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return mysql_thread_create(background_psi_thread_key,
|
||||
&m_handle, nullptr, thread_func, this);
|
||||
) {
|
||||
DBUG_ASSERT(!thread_name.empty());
|
||||
|
||||
int err = mysql_thread_create(background_psi_thread_key, &m_handle, nullptr,
|
||||
thread_func, this);
|
||||
|
||||
if (!err) {
|
||||
/*
|
||||
mysql_thread_create() ends up doing some work underneath and setting the
|
||||
thread name as "my-func". This isn't what we want. Our intent is to name
|
||||
the threads according to their purpose so that when displayed under the
|
||||
debugger then they'll be more easily identifiable. Therefore we'll reset
|
||||
the name if thread was successfully created.
|
||||
*/
|
||||
err = pthread_setname_np(m_handle, thread_name.c_str());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void Rdb_thread::signal(const bool &stop_thread)
|
||||
{
|
||||
void Rdb_thread::signal(const bool &stop_thread) {
|
||||
mysql_mutex_lock(&m_signal_mutex);
|
||||
if (stop_thread) {
|
||||
m_stop= true;
|
||||
m_stop = true;
|
||||
}
|
||||
mysql_cond_signal(&m_signal_cond);
|
||||
mysql_mutex_unlock(&m_signal_mutex);
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
#pragma once
|
||||
|
||||
/* C++ standard header files */
|
||||
#include <string>
|
||||
|
||||
/* MySQL includes */
|
||||
#include "./my_global.h"
|
||||
#include <mysql/psi/mysql_table.h>
|
||||
|
@ -26,91 +29,81 @@
|
|||
|
||||
namespace myrocks {
|
||||
|
||||
class Rdb_thread
|
||||
{
|
||||
private:
|
||||
class Rdb_thread {
|
||||
private:
|
||||
// Disable Copying
|
||||
Rdb_thread(const Rdb_thread&);
|
||||
Rdb_thread& operator=(const Rdb_thread&);
|
||||
Rdb_thread(const Rdb_thread &);
|
||||
Rdb_thread &operator=(const Rdb_thread &);
|
||||
|
||||
// Make sure we run only once
|
||||
std::atomic_bool m_run_once;
|
||||
|
||||
pthread_t m_handle;
|
||||
pthread_t m_handle;
|
||||
|
||||
protected:
|
||||
mysql_mutex_t m_signal_mutex;
|
||||
mysql_cond_t m_signal_cond;
|
||||
bool m_stop= false;
|
||||
protected:
|
||||
mysql_mutex_t m_signal_mutex;
|
||||
mysql_cond_t m_signal_cond;
|
||||
bool m_stop = false;
|
||||
|
||||
public:
|
||||
public:
|
||||
Rdb_thread() : m_run_once(false) {}
|
||||
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
void init(my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
||||
my_core::PSI_cond_key stop_bg_psi_cond_key);
|
||||
int create_thread(
|
||||
my_core::PSI_thread_key background_psi_thread_key);
|
||||
void init(my_core::PSI_mutex_key stop_bg_psi_mutex_key,
|
||||
my_core::PSI_cond_key stop_bg_psi_cond_key);
|
||||
int create_thread(const std::string &thread_name,
|
||||
my_core::PSI_thread_key background_psi_thread_key);
|
||||
#else
|
||||
void init();
|
||||
int create_thread();
|
||||
int create_thread(const std::string &thread_name);
|
||||
#endif
|
||||
|
||||
virtual void run(void) = 0;
|
||||
|
||||
void signal(const bool &stop_thread= false);
|
||||
void signal(const bool &stop_thread = false);
|
||||
|
||||
int join()
|
||||
{
|
||||
return pthread_join(m_handle, nullptr);
|
||||
}
|
||||
int join() { return pthread_join(m_handle, nullptr); }
|
||||
|
||||
void uninit();
|
||||
|
||||
virtual ~Rdb_thread() {}
|
||||
|
||||
private:
|
||||
static void* thread_func(void* const thread_ptr);
|
||||
private:
|
||||
static void *thread_func(void *const thread_ptr);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
MyRocks background thread control
|
||||
N.B. This is on top of RocksDB's own background threads
|
||||
(@see rocksdb::CancelAllBackgroundWork())
|
||||
*/
|
||||
|
||||
class Rdb_background_thread : public Rdb_thread
|
||||
{
|
||||
private:
|
||||
bool m_save_stats= false;
|
||||
class Rdb_background_thread : public Rdb_thread {
|
||||
private:
|
||||
bool m_save_stats = false;
|
||||
|
||||
void reset()
|
||||
{
|
||||
void reset() {
|
||||
mysql_mutex_assert_owner(&m_signal_mutex);
|
||||
m_stop= false;
|
||||
m_save_stats= false;
|
||||
m_stop = false;
|
||||
m_save_stats = false;
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
virtual void run() override;
|
||||
|
||||
void request_save_stats()
|
||||
{
|
||||
void request_save_stats() {
|
||||
mysql_mutex_lock(&m_signal_mutex);
|
||||
m_save_stats= true;
|
||||
m_save_stats = true;
|
||||
mysql_mutex_unlock(&m_signal_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Drop index thread control
|
||||
*/
|
||||
|
||||
struct Rdb_drop_index_thread : public Rdb_thread
|
||||
{
|
||||
struct Rdb_drop_index_thread : public Rdb_thread {
|
||||
virtual void run() override;
|
||||
};
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -32,14 +32,12 @@ namespace myrocks {
|
|||
/*
|
||||
Skip past any spaces in the input
|
||||
*/
|
||||
const char* rdb_skip_spaces(const struct charset_info_st* const cs,
|
||||
const char *str)
|
||||
{
|
||||
const char *rdb_skip_spaces(const struct charset_info_st *const cs,
|
||||
const char *str) {
|
||||
DBUG_ASSERT(cs != nullptr);
|
||||
DBUG_ASSERT(str != nullptr);
|
||||
|
||||
while (my_isspace(cs, *str))
|
||||
{
|
||||
while (my_isspace(cs, *str)) {
|
||||
str++;
|
||||
}
|
||||
|
||||
|
@ -51,18 +49,15 @@ const char* rdb_skip_spaces(const struct charset_info_st* const cs,
|
|||
Note that str1 can be longer but we only compare up to the number
|
||||
of characters in str2.
|
||||
*/
|
||||
bool rdb_compare_strings_ic(const char* const str1, const char* const str2)
|
||||
{
|
||||
bool rdb_compare_strings_ic(const char *const str1, const char *const str2) {
|
||||
DBUG_ASSERT(str1 != nullptr);
|
||||
DBUG_ASSERT(str2 != nullptr);
|
||||
|
||||
// Scan through the strings
|
||||
size_t ii;
|
||||
for (ii = 0; str2[ii]; ii++)
|
||||
{
|
||||
for (ii = 0; str2[ii]; ii++) {
|
||||
if (toupper(static_cast<int>(str1[ii])) !=
|
||||
toupper(static_cast<int>(str2[ii])))
|
||||
{
|
||||
toupper(static_cast<int>(str2[ii]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -74,11 +69,10 @@ bool rdb_compare_strings_ic(const char* const str1, const char* const str2)
|
|||
Scan through an input string looking for pattern, ignoring case
|
||||
and skipping all data enclosed in quotes.
|
||||
*/
|
||||
const char* rdb_find_in_string(const char *str, const char *pattern,
|
||||
bool * const succeeded)
|
||||
{
|
||||
char quote = '\0';
|
||||
bool escape = false;
|
||||
const char *rdb_find_in_string(const char *str, const char *pattern,
|
||||
bool *const succeeded) {
|
||||
char quote = '\0';
|
||||
bool escape = false;
|
||||
|
||||
DBUG_ASSERT(str != nullptr);
|
||||
DBUG_ASSERT(pattern != nullptr);
|
||||
|
@ -86,38 +80,30 @@ const char* rdb_find_in_string(const char *str, const char *pattern,
|
|||
|
||||
*succeeded = false;
|
||||
|
||||
for ( ; *str; str++)
|
||||
{
|
||||
for (; *str; str++) {
|
||||
/* If we found a our starting quote character */
|
||||
if (*str == quote)
|
||||
{
|
||||
if (*str == quote) {
|
||||
/* If it was escaped ignore it */
|
||||
if (escape)
|
||||
{
|
||||
if (escape) {
|
||||
escape = false;
|
||||
}
|
||||
/* Otherwise we are now outside of the quoted string */
|
||||
else
|
||||
{
|
||||
else {
|
||||
quote = '\0';
|
||||
}
|
||||
}
|
||||
/* Else if we are currently inside a quoted string? */
|
||||
else if (quote != '\0')
|
||||
{
|
||||
else if (quote != '\0') {
|
||||
/* If so, check for the escape character */
|
||||
escape = !escape && *str == '\\';
|
||||
}
|
||||
/* Else if we found a quote we are starting a quoted string */
|
||||
else if (*str == '"' || *str == '\'' || *str == '`')
|
||||
{
|
||||
else if (*str == '"' || *str == '\'' || *str == '`') {
|
||||
quote = *str;
|
||||
}
|
||||
/* Else we are outside of a quoted string - look for our pattern */
|
||||
else
|
||||
{
|
||||
if (rdb_compare_strings_ic(str, pattern))
|
||||
{
|
||||
else {
|
||||
if (rdb_compare_strings_ic(str, pattern)) {
|
||||
*succeeded = true;
|
||||
return str;
|
||||
}
|
||||
|
@ -132,10 +118,9 @@ const char* rdb_find_in_string(const char *str, const char *pattern,
|
|||
/*
|
||||
See if the next valid token matches the specified string
|
||||
*/
|
||||
const char* rdb_check_next_token(const struct charset_info_st* const cs,
|
||||
const char *str, const char* const pattern,
|
||||
bool* const succeeded)
|
||||
{
|
||||
const char *rdb_check_next_token(const struct charset_info_st *const cs,
|
||||
const char *str, const char *const pattern,
|
||||
bool *const succeeded) {
|
||||
DBUG_ASSERT(cs != nullptr);
|
||||
DBUG_ASSERT(str != nullptr);
|
||||
DBUG_ASSERT(pattern != nullptr);
|
||||
|
@ -145,8 +130,7 @@ const char* rdb_check_next_token(const struct charset_info_st* const cs,
|
|||
str = rdb_skip_spaces(cs, str);
|
||||
|
||||
// See if the next characters match the pattern
|
||||
if (rdb_compare_strings_ic(str, pattern))
|
||||
{
|
||||
if (rdb_compare_strings_ic(str, pattern)) {
|
||||
*succeeded = true;
|
||||
return str + strlen(pattern);
|
||||
}
|
||||
|
@ -158,43 +142,35 @@ const char* rdb_check_next_token(const struct charset_info_st* const cs,
|
|||
/*
|
||||
Parse id
|
||||
*/
|
||||
const char* rdb_parse_id(const struct charset_info_st* const cs,
|
||||
const char *str, std::string * const id)
|
||||
{
|
||||
const char *rdb_parse_id(const struct charset_info_st *const cs,
|
||||
const char *str, std::string *const id) {
|
||||
DBUG_ASSERT(cs != nullptr);
|
||||
DBUG_ASSERT(str != nullptr);
|
||||
|
||||
// Move past any spaces
|
||||
str = rdb_skip_spaces(cs, str);
|
||||
|
||||
if (*str == '\0')
|
||||
{
|
||||
if (*str == '\0') {
|
||||
return str;
|
||||
}
|
||||
|
||||
char quote = '\0';
|
||||
if (*str == '`' || *str == '"')
|
||||
{
|
||||
if (*str == '`' || *str == '"') {
|
||||
quote = *str++;
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
const char* start = str;
|
||||
size_t len = 0;
|
||||
const char *start = str;
|
||||
|
||||
if (quote != '\0')
|
||||
{
|
||||
for ( ; ; )
|
||||
{
|
||||
if (*str == '\0')
|
||||
{
|
||||
if (quote != '\0') {
|
||||
for (;;) {
|
||||
if (*str == '\0') {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (*str == quote)
|
||||
{
|
||||
if (*str == quote) {
|
||||
str++;
|
||||
if (*str != quote)
|
||||
{
|
||||
if (*str != quote) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -202,27 +178,21 @@ const char* rdb_parse_id(const struct charset_info_st* const cs,
|
|||
str++;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!my_isspace(cs, *str) && *str != '(' && *str != ')' &&
|
||||
*str != '.' && *str != ',' && *str != '\0')
|
||||
{
|
||||
} else {
|
||||
while (!my_isspace(cs, *str) && *str != '(' && *str != ')' && *str != '.' &&
|
||||
*str != ',' && *str != '\0') {
|
||||
str++;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user requested the id create it and return it
|
||||
if (id != nullptr)
|
||||
{
|
||||
if (id != nullptr) {
|
||||
*id = std::string("");
|
||||
id->reserve(len);
|
||||
while (len--)
|
||||
{
|
||||
while (len--) {
|
||||
*id += *start;
|
||||
if (*start++ == quote)
|
||||
{
|
||||
if (*start++ == quote) {
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
@ -234,8 +204,8 @@ const char* rdb_parse_id(const struct charset_info_st* const cs,
|
|||
/*
|
||||
Skip id
|
||||
*/
|
||||
const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
|
||||
{
|
||||
const char *rdb_skip_id(const struct charset_info_st *const cs,
|
||||
const char *str) {
|
||||
DBUG_ASSERT(cs != nullptr);
|
||||
DBUG_ASSERT(str != nullptr);
|
||||
|
||||
|
@ -243,19 +213,16 @@ const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
|
|||
}
|
||||
|
||||
static const std::size_t rdb_hex_bytes_per_char = 2;
|
||||
static const std::array<char, 16> rdb_hexdigit =
|
||||
{
|
||||
{ '0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }
|
||||
};
|
||||
static const std::array<char, 16> rdb_hexdigit = {{'0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'a', 'b',
|
||||
'c', 'd', 'e', 'f'}};
|
||||
|
||||
/*
|
||||
Convert data into a hex string with optional maximum length.
|
||||
If the data is larger than the maximum length trancate it and append "..".
|
||||
*/
|
||||
std::string rdb_hexdump(const char *data, const std::size_t data_len,
|
||||
const std::size_t maxsize)
|
||||
{
|
||||
const std::size_t maxsize) {
|
||||
DBUG_ASSERT(data != nullptr);
|
||||
|
||||
// Count the elements in the string
|
||||
|
@ -264,8 +231,7 @@ std::string rdb_hexdump(const char *data, const std::size_t data_len,
|
|||
std::size_t len = elems * rdb_hex_bytes_per_char;
|
||||
std::string str;
|
||||
|
||||
if (maxsize != 0 && len > maxsize)
|
||||
{
|
||||
if (maxsize != 0 && len > maxsize) {
|
||||
// If the amount of output is too large adjust the settings
|
||||
// and leave room for the ".." at the end
|
||||
elems = (maxsize - 2) / rdb_hex_bytes_per_char;
|
||||
|
@ -276,34 +242,29 @@ std::string rdb_hexdump(const char *data, const std::size_t data_len,
|
|||
str.reserve(len);
|
||||
|
||||
// Loop through the input data and build the output string
|
||||
for (std::size_t ii = 0; ii < elems; ii++, data++)
|
||||
{
|
||||
uint8_t ch = (uint8_t) *data;
|
||||
for (std::size_t ii = 0; ii < elems; ii++, data++) {
|
||||
uint8_t ch = (uint8_t)*data;
|
||||
str += rdb_hexdigit[ch >> 4];
|
||||
str += rdb_hexdigit[ch & 0x0F];
|
||||
}
|
||||
|
||||
// If we can't fit it all add the ".."
|
||||
if (elems != data_len)
|
||||
{
|
||||
if (elems != data_len) {
|
||||
str += "..";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Attempt to access the database subdirectory to see if it exists
|
||||
*/
|
||||
bool rdb_database_exists(const std::string& db_name)
|
||||
{
|
||||
const std::string dir = std::string(mysql_real_data_home) + FN_DIRSEP
|
||||
+ db_name;
|
||||
struct st_my_dir* const dir_info = my_dir(dir.c_str(),
|
||||
MYF(MY_DONT_SORT | MY_WANT_STAT));
|
||||
if (dir_info == nullptr)
|
||||
{
|
||||
bool rdb_database_exists(const std::string &db_name) {
|
||||
const std::string dir =
|
||||
std::string(mysql_real_data_home) + FN_DIRSEP + db_name;
|
||||
struct st_my_dir *const dir_info =
|
||||
my_dir(dir.c_str(), MYF(MY_DONT_SORT | MY_WANT_STAT));
|
||||
if (dir_info == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -311,4 +272,4 @@ bool rdb_database_exists(const std::string& db_name)
|
|||
return true;
|
||||
}
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "rocksdb/slice.h"
|
||||
|
||||
#ifdef HAVE_JEMALLOC
|
||||
#include <jemalloc/jemalloc.h>
|
||||
#include <jemalloc/jemalloc.h>
|
||||
#endif
|
||||
|
||||
namespace myrocks {
|
||||
|
@ -38,7 +38,7 @@ namespace myrocks {
|
|||
|
||||
#ifndef interface
|
||||
#define interface struct
|
||||
#endif // interface
|
||||
#endif // interface
|
||||
|
||||
/*
|
||||
Introduce C-style pseudo-namespaces, a handy way to make code more readble
|
||||
|
@ -56,7 +56,7 @@ namespace myrocks {
|
|||
// to non-obvious MySQL functions, like the ones that do not start with well
|
||||
// known prefixes: "my_", "sql_", and "mysql_".
|
||||
#define my_core
|
||||
#endif // my_core
|
||||
#endif // my_core
|
||||
|
||||
/*
|
||||
The intent behind a SHIP_ASSERT() macro is to have a mechanism for validating
|
||||
|
@ -74,14 +74,14 @@ namespace myrocks {
|
|||
*/
|
||||
|
||||
#ifndef SHIP_ASSERT
|
||||
#define SHIP_ASSERT(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
my_safe_printf_stderr("\nShip assert failure: \'%s\'\n", #expr); \
|
||||
abort_with_stack_traces(); \
|
||||
} \
|
||||
#define SHIP_ASSERT(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
my_safe_printf_stderr("\nShip assert failure: \'%s\'\n", #expr); \
|
||||
abort_with_stack_traces(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif // SHIP_ASSERT
|
||||
#endif // SHIP_ASSERT
|
||||
|
||||
/*
|
||||
Assert a implies b.
|
||||
|
@ -97,23 +97,50 @@ namespace myrocks {
|
|||
a and b must be both true or both false.
|
||||
*/
|
||||
#ifndef DBUG_ASSERT_IFF
|
||||
#define DBUG_ASSERT_IFF(a, b) \
|
||||
#define DBUG_ASSERT_IFF(a, b) \
|
||||
DBUG_ASSERT(static_cast<bool>(a) == static_cast<bool>(b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
Intent behind this macro is to avoid manually typing the function name every
|
||||
time we want to add the debugging statement and use the compiler for this
|
||||
work. This avoids typical refactoring problems when one renames a function,
|
||||
but the tracing message doesn't get updated.
|
||||
|
||||
We could use __func__ or __FUNCTION__ macros, but __PRETTY_FUNCTION__
|
||||
contains the signature of the function as well as its bare name and provides
|
||||
therefore more context when interpreting the logs.
|
||||
*/
|
||||
#define DBUG_ENTER_FUNC() DBUG_ENTER(__PRETTY_FUNCTION__)
|
||||
|
||||
/*
|
||||
Error handling pattern used across MySQL abides by the following rules: "All
|
||||
functions that can report an error (usually an allocation error), should
|
||||
return 0/FALSE/false on success, 1/TRUE/true on failure."
|
||||
|
||||
https://dev.mysql.com/doc/internals/en/additional-suggestions.html has more
|
||||
details.
|
||||
|
||||
To increase the comprehension and readability of MyRocks codebase we'll use
|
||||
constants similar to ones from C standard (EXIT_SUCCESS and EXIT_FAILURE) to
|
||||
make sure that both failure and success paths are clearly identifiable. The
|
||||
definitions of FALSE and TRUE come from <my_global.h>.
|
||||
*/
|
||||
#define HA_EXIT_SUCCESS FALSE
|
||||
#define HA_EXIT_FAILURE TRUE
|
||||
|
||||
/*
|
||||
Generic constant.
|
||||
*/
|
||||
const size_t RDB_MAX_HEXDUMP_LEN= 1000;
|
||||
const size_t RDB_MAX_HEXDUMP_LEN = 1000;
|
||||
|
||||
/*
|
||||
Helper function to get an NULL terminated uchar* out of a given MySQL String.
|
||||
*/
|
||||
|
||||
inline uchar* rdb_mysql_str_to_uchar_str(my_core::String *str)
|
||||
{
|
||||
inline uchar *rdb_mysql_str_to_uchar_str(my_core::String *str) {
|
||||
DBUG_ASSERT(str != nullptr);
|
||||
return reinterpret_cast<uchar*>(str->c_ptr());
|
||||
return reinterpret_cast<uchar *>(str->c_ptr());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -121,17 +148,15 @@ inline uchar* rdb_mysql_str_to_uchar_str(my_core::String *str)
|
|||
given STL string.
|
||||
*/
|
||||
|
||||
inline const uchar* rdb_std_str_to_uchar_ptr(const std::string &str)
|
||||
{
|
||||
return reinterpret_cast<const uchar*>(str.data());
|
||||
inline const uchar *rdb_std_str_to_uchar_ptr(const std::string &str) {
|
||||
return reinterpret_cast<const uchar *>(str.data());
|
||||
}
|
||||
|
||||
/*
|
||||
Helper function to convert seconds to milliseconds.
|
||||
*/
|
||||
|
||||
constexpr int rdb_convert_sec_to_ms(int sec)
|
||||
{
|
||||
constexpr int rdb_convert_sec_to_ms(int sec) {
|
||||
return std::chrono::milliseconds(std::chrono::seconds(sec)).count();
|
||||
}
|
||||
|
||||
|
@ -140,10 +165,9 @@ constexpr int rdb_convert_sec_to_ms(int sec)
|
|||
given RocksDB item.
|
||||
*/
|
||||
|
||||
inline const uchar* rdb_slice_to_uchar_ptr(const rocksdb::Slice *item)
|
||||
{
|
||||
inline const uchar *rdb_slice_to_uchar_ptr(const rocksdb::Slice *item) {
|
||||
DBUG_ASSERT(item != nullptr);
|
||||
return reinterpret_cast<const uchar*>(item->data());
|
||||
return reinterpret_cast<const uchar *>(item->data());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -152,12 +176,11 @@ inline const uchar* rdb_slice_to_uchar_ptr(const rocksdb::Slice *item)
|
|||
scenario for cases where it has been verified that this intervention has
|
||||
noticeable benefits.
|
||||
*/
|
||||
inline int purge_all_jemalloc_arenas()
|
||||
{
|
||||
inline int purge_all_jemalloc_arenas() {
|
||||
#ifdef HAVE_JEMALLOC
|
||||
unsigned narenas = 0;
|
||||
size_t sz = sizeof(unsigned);
|
||||
char name[25] = { 0 };
|
||||
char name[25] = {0};
|
||||
|
||||
// Get the number of arenas first. Please see `jemalloc` documentation for
|
||||
// all the various options.
|
||||
|
@ -184,28 +207,28 @@ inline int purge_all_jemalloc_arenas()
|
|||
Helper functions to parse strings.
|
||||
*/
|
||||
|
||||
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)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
bool rdb_compare_strings_ic(const char* const str1, const char* const str2)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
bool rdb_compare_strings_ic(const char *const str1, const char *const str2)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
const char* rdb_find_in_string(const char *str, const char *pattern,
|
||||
bool * const succeeded)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
const char *rdb_find_in_string(const char *str, const char *pattern,
|
||||
bool *const succeeded)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
const char* rdb_check_next_token(const struct charset_info_st* const cs,
|
||||
const char *str, const char* const pattern,
|
||||
bool * const succeeded)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
const char *rdb_check_next_token(const struct charset_info_st *const cs,
|
||||
const char *str, const char *const pattern,
|
||||
bool *const succeeded)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
const char* rdb_parse_id(const struct charset_info_st* const cs,
|
||||
const char *str, std::string * const id)
|
||||
__attribute__((__nonnull__(1, 2), __warn_unused_result__));
|
||||
const char *rdb_parse_id(const struct charset_info_st *const cs,
|
||||
const char *str, std::string *const id)
|
||||
MY_ATTRIBUTE((__nonnull__(1, 2), __warn_unused_result__));
|
||||
|
||||
const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
|
||||
__attribute__((__nonnull__, __warn_unused_result__));
|
||||
const char *rdb_skip_id(const struct charset_info_st *const cs, const char *str)
|
||||
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
|
||||
|
||||
/*
|
||||
Helper functions to populate strings.
|
||||
|
@ -213,11 +236,11 @@ const char* rdb_skip_id(const struct charset_info_st* const cs, const char *str)
|
|||
|
||||
std::string rdb_hexdump(const char *data, const std::size_t data_len,
|
||||
const std::size_t maxsize = 0)
|
||||
__attribute__((__nonnull__));
|
||||
MY_ATTRIBUTE((__nonnull__));
|
||||
|
||||
/*
|
||||
Helper function to see if a database exists
|
||||
*/
|
||||
bool rdb_database_exists(const std::string& db_name);
|
||||
bool rdb_database_exists(const std::string &db_name);
|
||||
|
||||
} // namespace myrocks
|
||||
} // namespace myrocks
|
||||
|
|
Loading…
Reference in a new issue