mysql5/mysql-5.7.27/sql/ndb_local_schema.cc

289 lines
7.1 KiB
C++

/*
Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ndb_local_schema.h"
#ifndef MYSQL_SERVER
#define MYSQL_SERVER
#endif
#include "sql_class.h"
#include "sql_table.h"
#include "mdl.h"
#include "log.h"
#include "table_trigger_dispatcher.h"
#include "sql_trigger.h"
static const char *ndb_ext=".ndb";
bool Ndb_local_schema::Base::mdl_try_lock(void) const
{
MDL_request_list mdl_requests;
MDL_request global_request;
MDL_request schema_request;
MDL_request mdl_request;
MDL_REQUEST_INIT(&global_request,
MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
MDL_STATEMENT);
MDL_REQUEST_INIT(&schema_request,
MDL_key::SCHEMA, m_db, "", MDL_INTENTION_EXCLUSIVE,
MDL_TRANSACTION);
MDL_REQUEST_INIT(&mdl_request,
MDL_key::TABLE, m_db, m_name, MDL_EXCLUSIVE,
MDL_TRANSACTION);
mdl_requests.push_front(&mdl_request);
mdl_requests.push_front(&schema_request);
mdl_requests.push_front(&global_request);
if (m_thd->mdl_context.acquire_locks(&mdl_requests,
0 /* don't wait for lock */))
{
// Check that an error has been pushed to thd and then
// clear it since this is just a _try lock_
assert(m_thd->is_error());
m_thd->clear_error();
log_warning("Failed to acquire metadata lock");
return false;
}
DBUG_PRINT("info", ("acquired metadata lock"));
return true;
}
void Ndb_local_schema::Base::mdl_unlock(void)
{
m_thd->mdl_context.release_transactional_locks();
}
void Ndb_local_schema::Base::log_warning(const char* fmt, ...) const
{
char buf[1024];
va_list args;
va_start(args, fmt);
my_vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (m_push_warnings)
{
// Append the error which caused the error to thd's warning list
push_warning_printf(m_thd, Sql_condition::SL_NOTE,
ER_GET_ERRMSG, "Ndb schema[%s.%s]: %s",
m_db, m_name, buf);
}
else
{
// Print the warning to log file
sql_print_warning("Ndb schema[%s.%s]: %s",
m_db, m_name, buf);
}
}
Ndb_local_schema::Base::Base(THD* thd, const char* db, const char* name) :
m_thd(thd),
m_db(db), m_name(name)
{
/*
System(or daemon) threads report error to log file
all other threads use push_warning
*/
m_push_warnings = (thd->get_command() != COM_DAEMON);
m_have_mdl_lock= mdl_try_lock();
}
Ndb_local_schema::Base::~Base()
{
// Release MDL locks
if (m_have_mdl_lock)
{
DBUG_PRINT("info", ("releasing mdl lock"));
mdl_unlock();
}
}
bool
Ndb_local_schema::Table::file_exists(const char* ext) const
{
char buf[FN_REFLEN + 1];
build_table_filename(buf, sizeof(buf)-1,
m_db, m_name, ext, 0);
if (my_access(buf, F_OK))
{
DBUG_PRINT("info", ("File '%s' does not exist", buf));
return false;
}
DBUG_PRINT("info", ("File '%s' exist", buf));
return true;
}
bool
Ndb_local_schema::Table::remove_file(const char* ext) const
{
char buf[FN_REFLEN + 1];
build_table_filename(buf, sizeof(buf)-1,
m_db, m_name, ext, 0);
int error = my_delete(buf, 0);
if (!error || errno == ENOENT)
return true;
log_warning("Failed to remove file '%s', errno: %d", buf, errno);
return false;
}
bool
Ndb_local_schema::Table::rename_file(const char* new_db, const char* new_name,
const char* ext) const
{
char from[FN_REFLEN + 1];
build_table_filename(from, sizeof(from)-1,
m_db, m_name, ext, 0);
char to[FN_REFLEN + 1];
build_table_filename(to, sizeof(to) - 1, new_db, new_name, ext, 0);
int error = my_rename(from, to, 0);
if (!error)
return true;
log_warning("Failed to rename file '%s' to '%s', errno: %d",
from, to, errno);
return false;
}
// Read the engine type from .frm and return true if it says NDB
bool
Ndb_local_schema::Table::frm_engine_is_ndb(void) const
{
char buf[FN_REFLEN + 1];
build_table_filename(buf, sizeof(buf)-1,
m_db, m_name, reg_ext, 0);
legacy_db_type engine_type;
(void)dd_frm_type(m_thd, buf, &engine_type);
DBUG_PRINT("info", ("engine_type: %d", engine_type));
return (engine_type == DB_TYPE_NDBCLUSTER);
}
Ndb_local_schema::Table::Table(THD* thd,
const char* db, const char* name) :
Ndb_local_schema::Base(thd, db, name),
m_ndb_file_exist(false),
m_has_triggers(false)
{
DBUG_ENTER("Ndb_local_table");
DBUG_PRINT("enter", ("name: '%s.%s'", db, name));
// Check if .frm file exist
m_frm_file_exist = file_exists(reg_ext);
if (!m_frm_file_exist)
{
// Check for stray .ndb file
assert(!file_exists(ndb_ext));
DBUG_VOID_RETURN;
}
// Check if .ndb file exist
m_ndb_file_exist = file_exists(ndb_ext);
// Check if there are trigger files
m_has_triggers = file_exists(TRG_EXT);
DBUG_VOID_RETURN;
}
bool
Ndb_local_schema::Table::is_local_table(void) const
{
if (m_frm_file_exist && !m_ndb_file_exist)
{
// The .frm exist but no .ndb file , this is a "local" table
// Double check that the engine type in .frm doesn't say NDB
assert(!frm_engine_is_ndb());
return true;
}
return false;
}
void
Ndb_local_schema::Table::remove_table(void) const
{
(void)remove_file(reg_ext);
(void)remove_file(ndb_ext);
if (m_has_triggers)
{
// Copy to buffers since 'drop_all_triggers' want char*
char db_name_buf[FN_REFLEN + 1], table_name_buf[FN_REFLEN + 1];
my_stpcpy(db_name_buf, m_db);
my_stpcpy(table_name_buf, m_name);
if (drop_all_triggers(m_thd, db_name_buf, table_name_buf))
{
log_warning("Failed to drop all triggers");
}
}
}
void
Ndb_local_schema::Table::rename_table(const char* new_db,
const char* new_name) const
{
(void)rename_file(new_db, new_name, reg_ext);
(void)rename_file(new_db, new_name, ndb_ext);
if (m_has_triggers)
{
if (!have_mdl_lock())
{
// change_trigger_table_name() requires an EXLUSIVE mdl lock
// so if the mdl lock was not aquired, skip this part
log_warning("Can't rename triggers, no mdl lock");
}
else
{
if (change_trigger_table_name(m_thd,
m_db, m_name, m_name,
new_db, new_name))
{
log_warning("Failed to rename all triggers");
}
}
}
}