polardbxengine/storage/xengine/dict/xdb_cf_manager.cc

272 lines
8.5 KiB
C++

/*
Portions Copyright (c) 2020, Alibaba Group Holding Limited
Copyright (c) 2014, SkySQL Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
#endif
/* This C++ files header file */
#include "./xdb_cf_manager.h"
/* MyX header files */
#include "./ha_xengine.h"
#include "./ha_xengine_proto.h"
using namespace xengine;
using namespace db;
namespace myx {
/* Check if ColumnFamily name says it's a reverse-ordered CF */
bool Xdb_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))
return true;
else
return false;
}
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key ex_key_cfm;
#endif
void Xdb_cf_manager::init(
Xdb_cf_options *const cf_options,
std::vector<xengine::db::ColumnFamilyHandle *> *const handles,
Xdb_ddl_log_manager *ddl_log_manager) {
mysql_mutex_init(ex_key_cfm, &m_mutex, MY_MUTEX_INIT_FAST);
DBUG_ASSERT(cf_options != nullptr);
DBUG_ASSERT(handles != nullptr);
DBUG_ASSERT(ddl_log_manager != nullptr);
DBUG_ASSERT(handles->size() > 0);
m_cf_options = cf_options;
m_ddl_log_manager = ddl_log_manager;
for (auto cfh : *handles) {
DBUG_ASSERT(cfh != nullptr);
//m_cf_name_map[cfh->GetName()] = cfh;
m_subtable_id_map[cfh->GetID()] = cfh;
}
}
void Xdb_cf_manager::cleanup() {
for (auto it : m_subtable_id_map) {
MOD_DELETE_OBJECT(ColumnFamilyHandle, it.second);
}
mysql_mutex_destroy(&m_mutex);
}
/**
Generate Column Family name for per-index column families
@param res OUT Column Family name
*/
void Xdb_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;
}
/**
create subtable physically, for rollback, we need write ddl_log.
@param[in] xdb, xengine DB object
@param[in] xa_batch, all modify data cache in user transaction, be part of xa transaction, for create system subtable, no need write log and xa_batch is nullptr.
@param[in, thread_id, session thread_id
@param[in], subtable_name
@param[in/out], cf_handle, handler to operate subtable
*/
bool Xdb_cf_manager::create_subtable(db::DB *const xdb, db::WriteBatch *const xa_batch,
ulong thread_id, uint index_number,
const xengine::common::ColumnFamilyOptions &cf_options,
const char *subtable_name,
bool create_table_space,
int64_t &table_space_id,
db::ColumnFamilyHandle **cf_handle) {
/** create subtable physically */
const std::string subtable_name_str(subtable_name);
xengine::common::ColumnFamilyOptions opts;
m_cf_options->get_cf_options(subtable_name_str, &opts);
sql_print_information(
"XEngine: creating subtable: index_number(%d), subtable_name(%s)",
index_number, subtable_name_str.c_str());
/** write subtable log */
if (xa_batch != nullptr) {
if (m_ddl_log_manager->write_drop_subtable_log(
xa_batch, index_number, thread_id, false)) {
sql_print_error("XEngine: write drop_subtable_log error");
return true;
}
}
DBUG_EXECUTE_IF("ddl_log_crash_after_drop_subtable_log", DBUG_SUICIDE(););
struct xengine::db::CreateSubTableArgs args(index_number, cf_options, create_table_space, table_space_id);
const xengine::common::Status s =
xdb->CreateColumnFamily(args, cf_handle);
if (s.ok()) {
//m_cf_name_map[(*cf_handle)->GetName()] = *cf_handle;
m_subtable_id_map[(*cf_handle)->GetID()] = *cf_handle;
if (create_table_space) {
table_space_id = (reinterpret_cast<ColumnFamilyHandleImpl *>(*cf_handle))->cfd()->get_table_space_id();
}
}
sql_print_information("XEngine: creating subtable successfully. "
"index_number(%d), subtable_id(%d), subtable_name(%s)",
index_number, (*cf_handle)->GetID(), subtable_name_str.c_str());
return false;
}
/*
@brief
Find column family by name. If it doesn't exist, create it
@detail
See Xdb_cf_manager::get_cf
*/
xengine::db::ColumnFamilyHandle *Xdb_cf_manager::get_or_create_cf(
xengine::db::DB *const xdb, xengine::db::WriteBatch *write_batch,
ulong thread_id, uint subtable_id, const char *cf_name,
const std::string &db_table_name, const char *const index_name,
bool *const is_automatic, const xengine::common::ColumnFamilyOptions &cf_options,
bool create_table_space, int64_t &table_space_id) {
DBUG_ASSERT(xdb != nullptr);
XDB_MUTEX_LOCK_CHECK(m_mutex);
xengine::db::ColumnFamilyHandle *cf_handle = nullptr;
const auto it = m_subtable_id_map.find(subtable_id);
if (it != m_subtable_id_map.end())
cf_handle = it->second;
else {
if (!create_subtable(xdb, write_batch, thread_id, subtable_id, cf_options, cf_name, create_table_space, table_space_id, &cf_handle)) {
sql_print_information("XEngine: create subtable successfully, thread_id(%ld), "
"subtable_id(%d), cf_name(%s)",
thread_id, cf_handle->GetID(), cf_name);
} else {
cf_handle = nullptr;
sql_print_error(
"XEngine: create subtable failed, %ld, %d, %s", thread_id,
subtable_id, cf_name);
}
}
XDB_MUTEX_UNLOCK_CHECK(m_mutex);
return cf_handle;
}
/*
* drop cf specified by cf_id
*/
void
Xdb_cf_manager::drop_cf(xengine::db::DB *const xdb, const uint32_t cf_id) {
DBUG_ASSERT(xdb != nullptr);
xengine::db::ColumnFamilyHandle *cf_handle;
XDB_MUTEX_LOCK_CHECK(m_mutex);
const auto id_it = m_subtable_id_map.find(cf_id);
if (id_it != m_subtable_id_map.end()) {
cf_handle = id_it->second;
const xengine::common::Status s = xdb->DropColumnFamily(cf_handle);
if (!s.ok()) {
sql_print_information("XEngine: drop subtable failed %s", s.getState());
}
// remove it from the maps
//const auto name_it = m_cf_name_map.find(cf_handle->GetName().c_str());
//DBUG_ASSERT(name_it != m_cf_name_map.end());
m_subtable_id_map.erase(id_it);
//m_cf_name_map.erase(name_it);
MOD_DELETE_OBJECT(ColumnFamilyHandle, cf_handle);
} else {
sql_print_information("XEngine: can't find the subtable(%d) to drop", cf_id);
}
XDB_MUTEX_UNLOCK_CHECK(m_mutex);
}
xengine::db::ColumnFamilyHandle *Xdb_cf_manager::get_cf(const uint32_t &id) const {
xengine::db::ColumnFamilyHandle *cf_handle = nullptr;
XDB_MUTEX_LOCK_CHECK(m_mutex);
const auto it = m_subtable_id_map.find(id);
if (it != m_subtable_id_map.end())
cf_handle = it->second;
XDB_MUTEX_UNLOCK_CHECK(m_mutex);
return cf_handle;
}
/*
std::vector<std::string> Xdb_cf_manager::get_cf_names(void) const {
std::vector<std::string> names;
XDB_MUTEX_LOCK_CHECK(m_mutex);
for (auto it : m_cf_name_map) {
names.push_back(it.first);
}
XDB_MUTEX_UNLOCK_CHECK(m_mutex);
return names;
}
*/
std::vector<int32_t> Xdb_cf_manager::get_subtable_ids(void) const {
std::vector<int32_t> subtable_ids;
XDB_MUTEX_LOCK_CHECK(m_mutex);
for (auto it : m_subtable_id_map) {
subtable_ids.push_back(it.first);
}
XDB_MUTEX_UNLOCK_CHECK(m_mutex);
return subtable_ids;
}
std::vector<xengine::db::ColumnFamilyHandle *>
Xdb_cf_manager::get_all_cf(void) const {
std::vector<xengine::db::ColumnFamilyHandle *> list;
xengine::db::ColumnFamilyHandleImpl *handle_impl = nullptr;
XDB_MUTEX_LOCK_CHECK(m_mutex);
for (auto it : m_subtable_id_map) {
handle_impl = reinterpret_cast<xengine::db::ColumnFamilyHandleImpl *>(it.second);
// ref the cfd avoid delete and the caller need delete it
list.push_back(new xengine::db::ColumnFamilyHandleImpl(
handle_impl->cfd(), handle_impl->db(), handle_impl->mutex()));
}
XDB_MUTEX_UNLOCK_CHECK(m_mutex);
return list;
}
} // namespace myx