summaryrefslogtreecommitdiffstats
path: root/storage/tokudb/tokudb_dir_cmd.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
commita175314c3e5827eb193872241446f2f8f5c9d33c (patch)
treecd3d60ca99ae00829c52a6ca79150a5b6e62528b /storage/tokudb/tokudb_dir_cmd.cc
parentInitial commit. (diff)
downloadmariadb-10.5-upstream/1%10.5.12.tar.xz
mariadb-10.5-upstream/1%10.5.12.zip
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/tokudb/tokudb_dir_cmd.cc')
-rw-r--r--storage/tokudb/tokudb_dir_cmd.cc331
1 files changed, 331 insertions, 0 deletions
diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc
new file mode 100644
index 00000000..871bb712
--- /dev/null
+++ b/storage/tokudb/tokudb_dir_cmd.cc
@@ -0,0 +1,331 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
+/* -*- mode: C; c-basic-offset: 4 -*- */
+#ident "$Id$"
+/*======
+This file is part of TokuDB
+
+
+Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
+
+ TokuDBis is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2,
+ as published by the Free Software Foundation.
+
+ TokuDB 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 TokuDB. If not, see <http://www.gnu.org/licenses/>.
+
+======= */
+
+#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
+
+#include "hatoku_hton.h"
+#include "tokudb_dir_cmd.h"
+#include "my_dbug.h"
+#include "sql_base.h"
+
+#include <vector>
+#include <string>
+
+namespace tokudb {
+
+const char tokens_delimiter = ' ';
+const char tokens_escape_delimiter_char = '\\';
+
+static int MDL_and_TDC(THD *thd,
+ const char *db,
+ const char *table,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ LEX_CSTRING db_arg;
+ LEX_CSTRING table_arg;
+
+ db_arg.str = const_cast<char *>(db);
+ db_arg.length = strlen(db);;
+ table_arg.str = const_cast<char *>(table);
+ table_arg.length = strlen(table);
+ Table_ident table_ident(thd, &db_arg, &table_arg, true);;
+ thd->lex->first_select_lex()->add_table_to_list(
+ thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0);
+ /* The lock will be released at the end of mysq_execute_command() */
+ error = lock_table_names(thd,
+ thd->lex->first_select_lex()->table_list.first,
+ NULL,
+ thd->variables.lock_wait_timeout,
+ 0);
+ if (error) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ error,
+ "Can't lock table '%s.%s'",
+ db,
+ table);
+ return error;
+ }
+ tdc_remove_table(thd, db, table);
+ return error;
+}
+
+static bool parse_db_and_table(const char *dname,
+ std::string /*out*/ &db_name,
+ std::string /*out*/ &table_name) {
+ const char *begin;
+ const char *end;
+ const char *db_name_begin;
+ const char *db_name_end;
+
+ begin = strchr(dname, '/');
+ if (!begin)
+ return false;
+ ++begin;
+ end = strchr(begin, '/');
+ if (!end)
+ return false;
+
+ db_name_begin = begin;
+ db_name_end = end;
+
+ begin = end + 1;
+
+ end = strchr(begin, '-');
+ if (!end)
+ return false;
+
+ if (strncmp(end, "-main", strlen("-main")) &&
+ strncmp(end, "-status", strlen("-status")) &&
+ strncmp(end, "-key", strlen("-key")))
+ return false;
+
+ db_name.assign(db_name_begin, db_name_end);
+ table_name.assign(begin, end);
+
+ return true;
+}
+
+static int attach(THD *thd,
+ const std::string &dname,
+ const std::string &iname,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ DB_TXN* txn = NULL;
+ DB_TXN *parent_txn = NULL;
+ tokudb_trx_data *trx = NULL;
+
+ std::string db_name;
+ std::string table_name;
+
+ if (parse_db_and_table(dname.c_str(), db_name, table_name)) {
+ error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb);
+ if (error)
+ goto cleanup;
+ }
+
+ trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
+ if (trx && trx->sub_sp_level)
+ parent_txn = trx->sub_sp_level;
+ error = txn_begin(db_env, parent_txn, &txn, 0, thd);
+ if (error)
+ goto cleanup;
+
+ error = db_env->dirtool_attach(db_env,
+ txn,
+ dname.c_str(),
+ iname.c_str());
+cleanup:
+ if (txn) {
+ if (error) {
+ abort_txn(txn);
+ }
+ else {
+ commit_txn(txn, 0);
+ }
+ }
+ return error;
+}
+
+static int detach(THD *thd,
+ const std::string &dname,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ DB_TXN* txn = NULL;
+ DB_TXN *parent_txn = NULL;
+ tokudb_trx_data *trx = NULL;
+
+ std::string db_name;
+ std::string table_name;
+
+ if (parse_db_and_table(dname.c_str(), db_name, table_name)) {
+ error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb);
+ if (error)
+ goto cleanup;
+ }
+
+ trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
+ if (trx && trx->sub_sp_level)
+ parent_txn = trx->sub_sp_level;
+ error = txn_begin(db_env, parent_txn, &txn, 0, thd);
+ if (error)
+ goto cleanup;
+
+ error = db_env->dirtool_detach(db_env,
+ txn,
+ dname.c_str());
+cleanup:
+ if (txn) {
+ if (error) {
+ abort_txn(txn);
+ }
+ else {
+ commit_txn(txn, 0);
+ }
+ }
+ return error;
+}
+
+static int move(THD *thd,
+ const std::string &old_dname,
+ const std::string &new_dname,
+ const dir_cmd_callbacks &cb) {
+ int error;
+ DB_TXN* txn = NULL;
+ DB_TXN *parent_txn = NULL;
+ tokudb_trx_data *trx = NULL;
+
+ std::string db_name;
+ std::string table_name;
+
+ if (parse_db_and_table(old_dname.c_str(), db_name, table_name)) {
+ error = MDL_and_TDC(thd, db_name.c_str(), table_name.c_str(), cb);
+ if (error)
+ goto cleanup;
+ }
+
+ trx = (tokudb_trx_data *) thd_get_ha_data(thd, tokudb_hton);
+ if (trx && trx->sub_sp_level)
+ parent_txn = trx->sub_sp_level;
+ error = txn_begin(db_env, parent_txn, &txn, 0, thd);
+ if (error)
+ goto cleanup;
+
+ error = db_env->dirtool_move(db_env,
+ txn,
+ old_dname.c_str(),
+ new_dname.c_str());
+cleanup:
+ if (txn) {
+ if (error) {
+ abort_txn(txn);
+ }
+ else {
+ commit_txn(txn, 0);
+ }
+ }
+ return error;
+}
+
+static void tokenize(const char *cmd_str,
+ std::vector<std::string> /*out*/ &tokens) {
+ DBUG_ASSERT(cmd_str);
+
+ bool was_escape = false;
+ const char *token_begin = cmd_str;
+ const char *token_end = token_begin;
+
+ while (*token_end) {
+ if (*token_end == tokens_escape_delimiter_char) {
+ was_escape = true;
+ }
+ else if (*token_end == tokens_delimiter) {
+ if (was_escape)
+ was_escape = false;
+ else {
+ if (token_begin == token_end)
+ ++token_begin;
+ else {
+ tokens.push_back(std::string(token_begin, token_end));
+ token_begin = token_end + 1;
+ }
+ }
+ }
+ else {
+ was_escape = false;
+ }
+ ++token_end;
+ }
+
+ if (token_begin != token_end)
+ tokens.push_back(std::string(token_begin, token_end));
+}
+
+void process_dir_cmd(THD *thd,
+ const char *cmd_str,
+ const dir_cmd_callbacks &cb) {
+
+ DBUG_ASSERT(thd);
+ DBUG_ASSERT(cmd_str);
+
+ std::vector<std::string> tokens;
+ tokenize(cmd_str, tokens);
+
+ if (tokens.empty())
+ return;
+
+ const std::string &cmd = tokens[0];
+
+ if (!cmd.compare("attach")) {
+ if (tokens.size() != 3) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ EINVAL,
+ "attach command requires two arguments");
+ }
+ else {
+ int r = attach(thd, tokens[1], tokens[2], cb);
+ if (r && cb.set_error)
+ cb.set_error(thd, r, "Attach command error");
+ }
+ }
+ else if (!cmd.compare("detach")) {
+ if (tokens.size() != 2) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ EINVAL,
+ "detach command requires one argument");
+ }
+ else {
+ int r = detach(thd, tokens[1], cb);
+ if (r && cb.set_error)
+ cb.set_error(thd, r, "detach command error");
+ }
+ }
+ else if (!cmd.compare("move")) {
+ if (tokens.size() != 3) {
+ if (cb.set_error)
+ cb.set_error(thd,
+ EINVAL,
+ "move command requires two arguments");
+ }
+ else {
+ int r = move(thd, tokens[1], tokens[2], cb);
+ if (r && cb.set_error)
+ cb.set_error(thd, r, "move command error");
+ }
+ }
+ else {
+ if (cb.set_error)
+ cb.set_error(thd,
+ ENOENT,
+ "Unknown command '%s'",
+ cmd.c_str());
+ }
+
+ return;
+};
+
+
+} // namespace tokudb