patch 4.0
This commit is contained in:
520
tools/ob_admin/server_tool/ob_admin_routine.cpp
Normal file
520
tools/ob_admin/server_tool/ob_admin_routine.cpp
Normal file
@ -0,0 +1,520 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#include "ob_admin_routine.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <unistd.h>
|
||||
#include "ob_admin_utils.h"
|
||||
#include "share/ob_rpc_struct.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "lib/time/ob_time_utility.h" // ObTimeUtility
|
||||
#define ADMIN_WARN(format, ...) fprintf(stderr, format "\n", ##__VA_ARGS__)
|
||||
#define DEF_COMMAND(t, cmd, v...) \
|
||||
namespace oceanbase { \
|
||||
namespace tools { \
|
||||
class ObAdmin_##cmd \
|
||||
: public ObAdminRoutine \
|
||||
{ \
|
||||
public: \
|
||||
ObAdmin_##cmd() \
|
||||
: ObAdminRoutine(#cmd, ##v) \
|
||||
{ t; g_routines.push_back(this); } \
|
||||
virtual int process(); \
|
||||
} command_##cmd; }} \
|
||||
int ObAdmin_##cmd::process()
|
||||
|
||||
#define TRANS target_="TRX"
|
||||
#define SERVER target_="SVR"
|
||||
|
||||
using namespace oceanbase::tools;
|
||||
using namespace oceanbase::common;
|
||||
|
||||
namespace oceanbase {
|
||||
namespace tools {
|
||||
std::vector<ObAdminRoutine*> g_routines;
|
||||
} /* end of namespace tools */
|
||||
} /* end of namespace oceanbase */
|
||||
|
||||
ObAdminRoutine::ObAdminRoutine(const string &action_name, int version, const string &args)
|
||||
: action_name_(action_name), version_(version), timeout_(3000000)
|
||||
{
|
||||
args_ = args;
|
||||
}
|
||||
|
||||
ObAdminRoutine::~ObAdminRoutine()
|
||||
{}
|
||||
|
||||
bool ObAdminRoutine::match(const string &cmd) const
|
||||
{
|
||||
string action;
|
||||
string::size_type pos;
|
||||
pos = cmd.find(" ");
|
||||
action = cmd.substr(0, pos);
|
||||
return action == action_name_;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, dump_memtable, 1, "tenant_id:ls_id:tablet_id # dump memtable to /tmp/memtable.*")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string arg_str;
|
||||
uint64_t tablet_id;
|
||||
obrpc::ObDumpMemtableArg arg;
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide partition_key");
|
||||
} else {
|
||||
arg_str = cmd_.substr(action_name_.length() + 1);
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (3 != sscanf(arg_str.c_str(), "%ld:%ld:%ld", &arg.tenant_id_, &arg.ls_id_, &tablet_id)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid arg", K(ret));
|
||||
} else if (FALSE_IT(arg.tablet_id_ = tablet_id)) {
|
||||
} else if (OB_SUCCESS != (ret = client_->dump_memtable(arg))) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "dump_memtable", K(arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, dump_tx_data_memtable, 1, "tenant_id:ls_id # dump tx data memtable to /tmp/tx_data_memtable.*")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string arg_str;
|
||||
obrpc::ObDumpTxDataMemtableArg arg;
|
||||
if (cmd_.length() <= action_name_.length()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("cmd is not completed.");
|
||||
} else {
|
||||
arg_str = cmd_.substr(action_name_.length() + 1);
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (2 != sscanf(arg_str.c_str(), "%ld:%ld", &arg.tenant_id_, &arg.ls_id_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid arg", K(ret));
|
||||
} else if (OB_SUCCESS != (ret = client_->dump_tx_data_memtable(arg))) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "dump_tx_data_memtable", K(arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, dump_single_tx_data, 1, "tenant_id:ls_id:tx_id # dump a single tx data to /tmp/single_tx_data.*")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string arg_str;
|
||||
obrpc::ObDumpSingleTxDataArg arg;
|
||||
if (cmd_.length() <= action_name_.length()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("cmd is not completed");
|
||||
} else {
|
||||
arg_str = cmd_.substr(action_name_.length() + 1);
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (3 != sscanf(arg_str.c_str(), "%ld:%ld:%ld", &arg.tenant_id_, &arg.ls_id_, &arg.tx_id_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid arg", KR(ret));
|
||||
} else if (OB_SUCCESS != (ret = client_->dump_single_tx_data(arg))) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "dump_single_tx_data", K(arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, force_set_replica_num, 1, "table_id:partition_idx:partition_cnt replica_num # force set replica_num")
|
||||
{
|
||||
return OB_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, force_set_parent, 1, "table_id:partition_idx:partition_cnt ip:port # force set parent")
|
||||
{
|
||||
return OB_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, force_set_server_list, 1, "replica_num ip:port ip:port ... #force set server list")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
string replica_num_str;
|
||||
ObAddr server;
|
||||
string server_str;
|
||||
obrpc::ObForceSetServerListArg arg;
|
||||
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide replica_num and ip:port");
|
||||
} else {
|
||||
string cmd_tail = cmd_.substr(action_name_.length() + 1);
|
||||
string::size_type pos;
|
||||
pos = cmd_tail.find(" ");
|
||||
if (pos == string::npos) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide replica_num and ip:port");
|
||||
} else {
|
||||
replica_num_str = cmd_tail.substr(0, pos);
|
||||
arg.replica_num_ = atoi(replica_num_str.c_str());
|
||||
|
||||
cmd_tail = cmd_tail.substr(pos + 1);
|
||||
|
||||
while ((pos = cmd_tail.find(" ")) != string::npos && OB_SUCC(ret)) {
|
||||
server_str = cmd_tail.substr(0, pos);
|
||||
if (OB_FAIL(server.parse_from_cstring(server_str.c_str()))) {
|
||||
ADMIN_WARN("server parse_from_cstring failed");
|
||||
} else if (OB_FAIL(arg.server_list_.push_back(server))) {
|
||||
ADMIN_WARN("server_list_ push_back failed");
|
||||
} else {
|
||||
cmd_tail = cmd_tail.substr(pos+1);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(server.parse_from_cstring(cmd_tail.c_str()))) {
|
||||
ADMIN_WARN("server parse_from_cstring failed");
|
||||
} else if (OB_FAIL(arg.server_list_.push_back(server))) {
|
||||
ADMIN_WARN("server_list_ push_back failed");
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(client_->force_set_server_list(arg))) {
|
||||
COMMON_LOG(ERROR, "force_set_server_list failed", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
COMMON_LOG(INFO, "force_set_server_list", K(ret), "replica_num", arg.replica_num_, "server_list", arg.server_list_);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, halt_all_prewarming, 1, "# halt all warming up, release memstores")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_SUCCESS != (ret = client_->halt_all_prewarming())) {
|
||||
COMMON_LOG(ERROR, "halt_all_warming_up", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, set_server_config, 1, "#set config")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string sstr;
|
||||
ObString config_str;
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide partition_key");
|
||||
} else {
|
||||
sstr = cmd_.substr(action_name_.length() + 1);
|
||||
config_str.assign_ptr(sstr.c_str(), static_cast<int32_t>(sstr.length()));
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_SUCCESS != client_->set_config(config_str)) {
|
||||
COMMON_LOG(ERROR, "add config failed.", K(config_str), K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, set_tenant_config, 1, "tenant_id config_item1=config_value1,config_item2=config_value2 # set tenant config")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string arg_str;
|
||||
ObTenantConfigArg arg;
|
||||
string::size_type pos;
|
||||
string tenant_id_str;
|
||||
string config_str;
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide partition_key");
|
||||
} else {
|
||||
arg_str = cmd_.substr(action_name_.length() + 1);
|
||||
// resolve tenant_id
|
||||
pos = arg_str.find(" ");
|
||||
if (pos == string::npos) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid format", K(ret), "str", arg_str.c_str());
|
||||
} else {
|
||||
tenant_id_str = arg_str.substr(0, pos);
|
||||
char *end_ptr = NULL;
|
||||
arg.tenant_id_ = strtoll(tenant_id_str.c_str(), &end_ptr, 10);
|
||||
if (*end_ptr != '\0') {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid format", K(ret), "str", arg_str.c_str());
|
||||
}
|
||||
}
|
||||
// resolve config_str
|
||||
if (OB_SUCC(ret)) {
|
||||
pos = arg_str.find_first_not_of(' ', pos);
|
||||
if (pos == string::npos) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid format", K(ret), "str", arg_str.c_str());
|
||||
} else {
|
||||
config_str = arg_str.substr(pos);
|
||||
if (config_str.length() > common::OB_MAX_EXTRA_CONFIG_LENGTH) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
COMMON_LOG(WARN, "invalid config str length", K(ret), "str", arg_str.c_str());
|
||||
} else {
|
||||
arg.config_str_.assign_ptr(config_str.c_str(), config_str.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_SUCCESS != client_->set_tenant_config(arg)) {
|
||||
COMMON_LOG(ERROR, "add tenant config failed.", K(arg), K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "set_tenant_config", K(ret), K(arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, diag, 1, "#login OceanBase")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char buf[1024];
|
||||
ObString argstr(1024, 0, buf);
|
||||
if (OB_FAIL(client_->get_diagnose_args(argstr))) {
|
||||
ADMIN_WARN("get diagnose args from observer fail, ret: %d", ret);
|
||||
} else {
|
||||
vector<string> args;
|
||||
tools::split(string(argstr.ptr(), argstr.length()), ' ', args);
|
||||
for (vector<string>::const_iterator it = args.begin();
|
||||
it != args.end();
|
||||
it++) {
|
||||
cout << *it << endl;
|
||||
}
|
||||
tools::execv("/usr/bin/mysql", args);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_switch_ilog_file, 1, "#force switch ilog file")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
obrpc::ObForceSwitchILogFileArg arg;
|
||||
arg.force_ = true;
|
||||
if (OB_SUCCESS != (ret = client_->force_switch_ilog_file(arg))) {
|
||||
COMMON_LOG(ERROR, "send req failed", K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "force_switch_ilog_file", K(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_set_all_as_single_replica, 1, "#force set all as single replica")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
obrpc::ObForceSetAllAsSingleReplicaArg arg;
|
||||
arg.force_ = true;
|
||||
if (OB_SUCCESS != (ret = client_->force_set_all_as_single_replica(arg))) {
|
||||
COMMON_LOG(ERROR, "send req failed", K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "force_set_all_as_single_replica", K(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_create_sys_table, 1, "tenant_id:table_id:last_replay_log_id # force create sys table")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string arg_str;
|
||||
obrpc::ObForceCreateSysTableArg arg;
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide tenant_id:table_id:last_replay_log_id");
|
||||
} else {
|
||||
arg_str = cmd_.substr(action_name_.length() + 1);
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (3 != sscanf(arg_str.c_str(), "%ld:%ld:%ld", &arg.tenant_id_, &arg.table_id_, &arg.last_replay_log_id_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid arg", K(ret));
|
||||
} else if (OB_SUCCESS != (ret = client_->force_create_sys_table(arg))) {
|
||||
COMMON_LOG(ERROR, "send req failed", K(ret));
|
||||
}
|
||||
COMMON_LOG(INFO, "force create sys table", K(ret), K(arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_set_locality, 1, "tenant_id locality # force set locality")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string arg_str;
|
||||
obrpc::ObForceSetLocalityArg arg;
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide tenant_id/locality");
|
||||
} else {
|
||||
arg_str = cmd_.substr(action_name_.length() + 1);
|
||||
string::size_type pos;
|
||||
string tenant_id_str;
|
||||
string locality_str;
|
||||
// resolve tenant_id
|
||||
pos = arg_str.find(" ");
|
||||
if (pos == string::npos) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid format", K(ret), "str", arg_str.c_str());
|
||||
} else {
|
||||
tenant_id_str = arg_str.substr(0, pos);
|
||||
char *end_ptr = NULL;
|
||||
arg.exec_tenant_id_ = strtoll(tenant_id_str.c_str(), &end_ptr, 10);
|
||||
if (*end_ptr != '\0') {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid format", K(ret), "str", arg_str.c_str());
|
||||
}
|
||||
}
|
||||
// resolve locality
|
||||
if (OB_SUCC(ret)) {
|
||||
pos = arg_str.find_first_not_of(' ', pos);
|
||||
if (pos == string::npos) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid format", K(ret), "str", arg_str.c_str());
|
||||
} else {
|
||||
locality_str = arg_str.substr(pos);
|
||||
if (locality_str.length() > common::MAX_LOCALITY_LENGTH) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
COMMON_LOG(WARN, "invalid locality str length", K(ret), "str", arg_str.c_str());
|
||||
} else {
|
||||
arg.locality_.assign_ptr(locality_str.c_str(), locality_str.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(client_->force_set_locality(arg))) {
|
||||
COMMON_LOG(ERROR, "send req failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
COMMON_LOG(INFO, "force set locality", K(ret), K(arg));
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_disable_blacklist, 1, "# force disable blacklist")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
if (OB_SUCCESS != (ret = client_->force_disable_blacklist())) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_enable_blacklist, 1, "# force enable blacklist")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
if (OB_SUCCESS != (ret = client_->force_enable_blacklist())) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_clear_blacklist, 1, "# force clear blacklist")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
if (OB_SUCCESS != (ret = client_->force_clear_srv_blacklist())) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, force_switch_leader, 1, "table_id:partition_idx:partition_cnt ip:port # force switch leader")
|
||||
{
|
||||
return OB_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, batch_switch_rs_leader, 1, "ip:port # batch switch rs leader")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
string pkey_str;
|
||||
string new_parent_str; // ip:port
|
||||
ObAddr new_leader;
|
||||
obrpc::ObSwitchLeaderArg arg;
|
||||
ObString cmd;
|
||||
ObString action_name;
|
||||
cmd.assign_ptr(cmd_.c_str(), static_cast<int32_t>(cmd_.length()));
|
||||
action_name.assign_ptr(action_name_.c_str(), static_cast<int32_t>(action_name_.length()));
|
||||
if (OB_UNLIKELY(cmd_ == action_name_)) {
|
||||
new_leader.reset();
|
||||
COMMON_LOG(INFO, "addr is default, auto batch switch rs leader",
|
||||
K(cmd), K(action_name));
|
||||
} else {
|
||||
new_parent_str = cmd_.substr(action_name_.length() + 1);
|
||||
if (OB_SUCCESS != (ret = new_leader.parse_from_cstring(new_parent_str.c_str()))) {
|
||||
COMMON_LOG(ERROR, "new_leader.parse_from_cstring fail", K(new_parent_str.c_str()),
|
||||
KR(ret), K(cmd), K(action_name));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (OB_ISNULL(client_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "client_ is NULL", KR(ret));
|
||||
} else if (OB_SUCCESS != (ret = client_->batch_switch_rs_leader(new_leader))) {
|
||||
COMMON_LOG(ERROR, "send batch switch rs leader req fail",
|
||||
KR(ret), K(new_leader), K(cmd), K(action_name));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, batch_switch_leader, 1, "[table_id:partition_idx;] ip:port # batch switch leader")
|
||||
{
|
||||
return OB_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
DEF_COMMAND(SERVER, modify_tenant_memory, 1,
|
||||
"tenant_id:memory_size:refresh_interval(s) # modify_tenant_memory")
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t tenant_id = 0;
|
||||
int64_t memory_size = 0;
|
||||
int64_t refresh_interval = 0;
|
||||
obrpc::ObTenantMemoryArg tenant_memory;
|
||||
if (cmd_ == action_name_) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ADMIN_WARN("should provide tenant_id and memory_size");
|
||||
} else {
|
||||
string cmd_tail = cmd_.substr(action_name_.length() + 1);
|
||||
if (3 != sscanf(cmd_tail.c_str(), "%ld:%ld:%ld", &tenant_id, &memory_size, &refresh_interval)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
COMMON_LOG(WARN, "invalid argument", K(ret), K(tenant_id), K(memory_size), K(refresh_interval));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else {
|
||||
tenant_memory.tenant_id_ = tenant_id;
|
||||
tenant_memory.memory_size_ = memory_size;
|
||||
tenant_memory.refresh_interval_ = refresh_interval;
|
||||
COMMON_LOG(INFO, "tenant_id, memory_size, refresh_interval", K(tenant_id),
|
||||
K(memory_size), K(refresh_interval));
|
||||
if (OB_SUCCESS != (ret = client_->update_tenant_memory(tenant_memory))) {
|
||||
COMMON_LOG(ERROR, "send req fail", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEF_COMMAND(TRANS, kill_part_trans_ctx, 1,
|
||||
"partition_id:partition_cnt:table_id trans_inc:timestamp svr_ip svr_port # kill_part_trans_ctx")
|
||||
{
|
||||
return OB_NOT_SUPPORTED;
|
||||
}
|
||||
94
tools/ob_admin/server_tool/ob_admin_routine.h
Normal file
94
tools/ob_admin/server_tool/ob_admin_routine.h
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef _OBADMIN_ROUTINE_H_
|
||||
#define _OBADMIN_ROUTINE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "lib/net/ob_addr.h"
|
||||
#include "share/ob_srv_rpc_proxy.h"
|
||||
#include "rpc/obrpc/ob_net_client.h"
|
||||
#include "share/ob_rpc_struct.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace oceanbase {
|
||||
using namespace common;
|
||||
namespace tools {
|
||||
class ObAdminRoutine
|
||||
{
|
||||
public:
|
||||
ObAdminRoutine(const string &action_name, int version = 1, const string &args = "");
|
||||
virtual ~ObAdminRoutine();
|
||||
|
||||
virtual int process() = 0;
|
||||
|
||||
bool match(const string &cmd) const;
|
||||
void set_command(const string &cmd)
|
||||
{
|
||||
cmd_ = cmd;
|
||||
}
|
||||
void set_timeout(int64_t timeout)
|
||||
{
|
||||
timeout_ = timeout;
|
||||
}
|
||||
|
||||
const string& action_name() const
|
||||
{
|
||||
return action_name_;
|
||||
}
|
||||
|
||||
const string& target() const
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
|
||||
const string usage() const
|
||||
{
|
||||
return action_name_ + " " + args_;
|
||||
}
|
||||
|
||||
void set_client(obrpc::ObSrvRpcProxy* client) { client_ = client; }
|
||||
protected:
|
||||
const string action_name_;
|
||||
string args_;
|
||||
string cmd_;
|
||||
const int version_;
|
||||
int64_t timeout_;
|
||||
string target_;
|
||||
obrpc::ObSrvRpcProxy* client_;
|
||||
}; /* end of class ObAdminRoutine */
|
||||
|
||||
|
||||
class RoutineComparer
|
||||
{
|
||||
public:
|
||||
RoutineComparer(const string &cmd)
|
||||
: cmd_(cmd)
|
||||
{}
|
||||
|
||||
bool operator ()(ObAdminRoutine *routine)
|
||||
{
|
||||
return routine->match(cmd_);
|
||||
}
|
||||
private:
|
||||
const string &cmd_;
|
||||
}; /* end of class RoutineComparer */
|
||||
|
||||
extern std::vector<ObAdminRoutine*> g_routines;
|
||||
|
||||
} /* end of namespace tools */
|
||||
} /* end of namespace oceanbase */
|
||||
|
||||
#endif /* _OBADMIN_ROUTINE_H_ */
|
||||
246
tools/ob_admin/server_tool/ob_admin_server_executor.cpp
Normal file
246
tools/ob_admin/server_tool/ob_admin_server_executor.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#include "ob_admin_server_executor.h"
|
||||
#include <getopt.h>
|
||||
#include <stddef.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <iomanip>
|
||||
#include "observer/ob_srv_network_frame.h"
|
||||
#include "lib/utility/ob_print_utils.h"
|
||||
#include "ob_admin_routine.h"
|
||||
using namespace std;
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::tools;
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace tools
|
||||
{
|
||||
const std::string ObAdminServerExecutor::DEFAULT_HOST = "127.1";
|
||||
const int ObAdminServerExecutor::DEFAULT_PORT = 2500;
|
||||
const int64_t ObAdminServerExecutor::DEFAULT_TIMEOUT = 3000000; /* 3s */
|
||||
|
||||
static const char *optstring = "h:p:t:s:m:S:";
|
||||
static struct option long_options[] = {
|
||||
{"host", 1, NULL, 'h'},
|
||||
{"port", 1, NULL, 'p'},
|
||||
{"timeout", 1, NULL, 't'},
|
||||
{"ssl-mode", 1, NULL, 's'},
|
||||
{"ssl-cfg-mode", 1, NULL, 'm'},
|
||||
{"sock_path", 1, NULL, 'S'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
ObAdminServerExecutor::ObAdminServerExecutor()
|
||||
: inited_(false),
|
||||
timeout_(DEFAULT_TIMEOUT),
|
||||
ssl_mode_(SSL_MODE_NONE),
|
||||
ssl_cfg_mode_(0)
|
||||
{}
|
||||
|
||||
ObAdminServerExecutor::~ObAdminServerExecutor()
|
||||
{
|
||||
g_routines.clear();
|
||||
}
|
||||
|
||||
bool ObAdminServerExecutor::parse_command(int argc, char *argv[])
|
||||
{
|
||||
bool ret = true;
|
||||
int option_index = 0;
|
||||
int c;
|
||||
string host = DEFAULT_HOST;
|
||||
int port = DEFAULT_PORT;
|
||||
bool has_ssl_opt = false;
|
||||
string ssl_str;
|
||||
string ssl_cfg_mode_str = "local";
|
||||
while (-1 != (c = getopt_long(argc, argv, optstring, long_options, &option_index)))
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'h':
|
||||
host = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
port = static_cast<int>(strtol(optarg, NULL, 10));
|
||||
break;
|
||||
case 't':
|
||||
timeout_ = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
case 's':
|
||||
ssl_str = optarg;
|
||||
has_ssl_opt = true;
|
||||
break;
|
||||
case 'm':
|
||||
ssl_cfg_mode_str = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
sock_path_ = optarg;
|
||||
break;
|
||||
case '?':
|
||||
case ':':
|
||||
ret = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (optind > argc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (optind == argc)
|
||||
{
|
||||
cerr << "no command specified!" << endl;
|
||||
return false;
|
||||
}
|
||||
if (port <= 0 || port >= 65536)
|
||||
{
|
||||
cerr << "port not valid: " << port << endl;
|
||||
return false;
|
||||
}
|
||||
if (has_ssl_opt) {
|
||||
if (0 == strcasecmp(ssl_str.c_str(), "INTL")) {
|
||||
ssl_mode_ = SSL_MODE_INTL;
|
||||
} else if (0 == strcasecmp(ssl_str.c_str(), "SM")) {
|
||||
ssl_mode_ = SSL_MODE_SM;
|
||||
} else {
|
||||
ssl_mode_ = SSL_MODE_INTL;
|
||||
}
|
||||
} else {
|
||||
ssl_mode_ = SSL_MODE_NONE;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(ssl_cfg_mode_str.c_str(), "local")) {
|
||||
ssl_cfg_mode_= 0;
|
||||
} else if (0 == strcasecmp(ssl_cfg_mode_str.c_str(), "bkmi")) {
|
||||
ssl_cfg_mode_ = 1;
|
||||
}
|
||||
if (sock_path_.size() > 0) {
|
||||
if (sock_path_.size() >= UNIX_PATH_MAX) {
|
||||
cerr << "The unix_domain_socket_path is too long! (No more than 15 characters)" << endl;
|
||||
ret = false;
|
||||
} else {
|
||||
dst_server_.set_unix_addr(sock_path_.c_str());
|
||||
}
|
||||
} else {
|
||||
dst_server_.set_ip_addr(host.c_str(), port);
|
||||
}
|
||||
|
||||
ostringstream ss;
|
||||
copy(argv + optind, argv + argc, ostream_iterator<char*>(ss, " "));
|
||||
cmd_ = ss.str();
|
||||
cmd_.erase(cmd_.end() - 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObAdminServerExecutor::usage() const
|
||||
{
|
||||
cerr << "============================================================================" << endl;
|
||||
cerr << "[USAGE]" << endl;
|
||||
cerr << "\tob_admin [OPTION] COMMAND" << endl;
|
||||
cerr << "[OPTION]" << endl;
|
||||
cerr << "\t-h host default 127.1" << endl;
|
||||
cerr << "\t-p port default 2500" << endl;
|
||||
cerr << "\t-t timeout default 3000000 (3s)" << endl;
|
||||
cerr << "\t-s ssl-mode intl or sm, default intl" << endl;
|
||||
cerr << "\t-m ssl-cfg-mode bkmi or local, default local" << endl;
|
||||
cerr << "\t-S unix_domain_socket_path" << endl;
|
||||
cerr << "[COMMAND]" << endl;
|
||||
for (vector<ObAdminRoutine*>::iterator it = g_routines.begin();
|
||||
it != g_routines.end();
|
||||
it++)
|
||||
{
|
||||
cerr << "\t" << left << setw(6) << (*it)->target() << ": " << (*it)->usage() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
static int ob_admin_server_read_bkmi_cfg(const char* buf, int64_t &sz)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
FILE *fp = NULL;
|
||||
const char* path = "obadmin_ssl_bkmi.cfg";
|
||||
if (OB_ISNULL(fp = fopen(path, "rb"))) {
|
||||
if (ENOENT == errno) {
|
||||
COMMON_LOG(ERROR, "obadmin_ssl_bkmi_cfg.txt is not exist");
|
||||
ret = OB_FILE_NOT_EXIST;
|
||||
} else {
|
||||
ret = OB_IO_ERROR;
|
||||
COMMON_LOG(ERROR, "cannot open file", K(path), K(errno));
|
||||
}
|
||||
} else {
|
||||
sz = fread((void *)buf, 1, OB_MAX_CONFIG_VALUE_LEN, fp);
|
||||
|
||||
if (OB_UNLIKELY(0 != ferror(fp))) {
|
||||
ret = OB_IO_ERROR;
|
||||
COMMON_LOG(ERROR, "read config file error", K(path), K(ret));
|
||||
} else if (OB_UNLIKELY(0 == feof(fp))) {
|
||||
ret = OB_BUF_NOT_ENOUGH;
|
||||
COMMON_LOG(ERROR, "config file is too long", K(path), K(ret));
|
||||
} else {
|
||||
COMMON_LOG(INFO, "read config file succ", K(path));
|
||||
}
|
||||
|
||||
if (OB_UNLIKELY(0 != fclose(fp))) {
|
||||
ret = OB_IO_ERROR;
|
||||
COMMON_LOG(ERROR, "Close config file failed", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObAdminServerExecutor::execute(int argc, char *argv[])
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!parse_command(argc, argv)) {
|
||||
usage();
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
} else if (OB_FAIL(client_.init())) {
|
||||
COMMON_LOG(WARN, "client init failed", K(ret));
|
||||
} else if (OB_FAIL(client_.get_proxy(srv_proxy_))) {
|
||||
COMMON_LOG(WARN, "get_proxy failed", K(ret));
|
||||
} else {
|
||||
srv_proxy_.set_server(dst_server_);
|
||||
srv_proxy_.set_timeout(timeout_);
|
||||
int64_t tenant_id = atoll(getenv("tenant")?:"0")?:OB_DIAG_TENANT_ID;
|
||||
srv_proxy_.set_tenant(tenant_id);
|
||||
inited_ = true;
|
||||
COMMON_LOG(INFO, "process", K(cmd_.c_str()), K_(timeout), K(tenant_id));
|
||||
vector<ObAdminRoutine*>::iterator it = find_if(g_routines.begin(), g_routines.end(), RoutineComparer(cmd_));
|
||||
if (it == g_routines.end()) {
|
||||
cerr << "Unknow command: " << cmd_ << endl;
|
||||
return false;
|
||||
}
|
||||
(*it)->set_timeout(timeout_);
|
||||
(*it)->set_command(cmd_);
|
||||
(*it)->set_client(&srv_proxy_);
|
||||
int ret = (*it)->process();
|
||||
COMMON_LOG(INFO, "process result:", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
62
tools/ob_admin/server_tool/ob_admin_server_executor.h
Normal file
62
tools/ob_admin/server_tool/ob_admin_server_executor.h
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef OB_ADMIN_SERVER_EXECUTOR_H_
|
||||
#define OB_ADMIN_SERVER_EXECUTOR_H_
|
||||
#include "../ob_admin_executor.h"
|
||||
#include "ob_admin_routine.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace tools
|
||||
{
|
||||
|
||||
class ObAdminServerExecutor : public ObAdminExecutor
|
||||
{
|
||||
public:
|
||||
enum SSL_MODE {
|
||||
SSL_MODE_NONE = 0,
|
||||
SSL_MODE_INTL = 1,
|
||||
SSL_MODE_SM = 2,
|
||||
};
|
||||
const char *const OB_CLIENT_SSL_CA_FILE = "wallet/ca.pem";
|
||||
const char *const OB_CLIENT_SSL_CERT_FILE = "wallet/client-cert.pem";
|
||||
const char *const OB_CLIENT_SSL_KEY_FILE = "wallet/client-key.pem";
|
||||
public:
|
||||
ObAdminServerExecutor();
|
||||
virtual ~ObAdminServerExecutor();
|
||||
virtual int execute(int argc, char *argv[]);
|
||||
int load_ssl_config();
|
||||
private:
|
||||
bool parse_command(int argc, char *argv[]);
|
||||
void usage() const;
|
||||
private:
|
||||
bool inited_;
|
||||
obrpc::ObNetClient client_;
|
||||
obrpc::ObSrvRpcProxy srv_proxy_;
|
||||
|
||||
common::ObAddr dst_server_;
|
||||
int64_t timeout_;
|
||||
std::string cmd_;
|
||||
SSL_MODE ssl_mode_;
|
||||
int ssl_cfg_mode_; //0 for local file mode, 1 for bkmi mode
|
||||
std::string sock_path_;
|
||||
|
||||
static const std::string DEFAULT_HOST;
|
||||
static const int DEFAULT_PORT;
|
||||
static const int64_t DEFAULT_TIMEOUT;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OB_ADMIN_SERVER_EXECUTOR_H_ */
|
||||
69
tools/ob_admin/server_tool/ob_admin_utils.h
Normal file
69
tools/ob_admin/server_tool/ob_admin_utils.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE is licensed under Mulan PubL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
||||
* You may obtain a copy of Mulan PubL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPubL-2.0
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PubL v2 for more details.
|
||||
*/
|
||||
|
||||
#ifndef _OB_ADMIN_UTILS_H_
|
||||
#define _OB_ADMIN_UTILS_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::stringstream;
|
||||
|
||||
#define NONE "\033[m"
|
||||
#define RED "\033[0;32;31m"
|
||||
#define LIGHT_RED "\033[1;31m"
|
||||
#define GREEN "\033[0;32;32m"
|
||||
#define LIGHT_GREEN "\033[1;32m"
|
||||
#define BLUE "\033[0;32;34m"
|
||||
#define LIGHT_BLUE "\033[1;34m"
|
||||
#define DARY_GRAY "\033[1;30m"
|
||||
#define CYAN "\033[0;36m"
|
||||
#define LIGHT_CYAN "\033[1;36m"
|
||||
#define PURPLE "\033[0;35m"
|
||||
#define LIGHT_PURPLE "\033[1;35m"
|
||||
#define BROWN "\033[0;33m"
|
||||
#define YELLOW "\033[1;33m"
|
||||
#define LIGHT_GRAY "\033[0;37m"
|
||||
#define WHITE "\033[1;37m"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace tools {
|
||||
void split(const string &s, char delim, vector<string> &elems)
|
||||
{
|
||||
stringstream ss(s);
|
||||
string item;
|
||||
while (getline(ss, item, delim)) {
|
||||
elems.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
void execv(const string &path, vector<string> &elems)
|
||||
{
|
||||
char *vec[1024] = {};
|
||||
if (elems.size() < 1024) {
|
||||
vec[0] = const_cast<char*>(path.c_str());
|
||||
for (size_t i = 0; i < elems.size(); ++i) {
|
||||
vec[i+1] = const_cast<char*>(elems[i].c_str());
|
||||
}
|
||||
::execv(path.c_str(), vec);
|
||||
}
|
||||
}
|
||||
} /* end of namespace tools */
|
||||
} /* end of namespace oceanbase */
|
||||
|
||||
#endif /* _OB_ADMIN_UTILS_H_ */
|
||||
Reference in New Issue
Block a user