358 lines
14 KiB
C++
358 lines
14 KiB
C++
/**
|
|
* 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 "lib/string/ob_string.h"
|
|
#include "share/config/ob_server_config.h"
|
|
#include "observer/virtual_table/ob_all_virtual_session_info.h"
|
|
#include "observer/ob_server.h"
|
|
#include "sql/session/ob_sql_session_info.h"
|
|
|
|
using namespace oceanbase::common;
|
|
namespace oceanbase
|
|
{
|
|
namespace observer
|
|
{
|
|
|
|
ObAllVirtualSessionInfo::ObAllVirtualSessionInfo()
|
|
: ObVirtualTableScannerIterator(),
|
|
session_mgr_(NULL),
|
|
fill_scanner_()
|
|
{
|
|
}
|
|
|
|
ObAllVirtualSessionInfo::~ObAllVirtualSessionInfo()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void ObAllVirtualSessionInfo::reset()
|
|
{
|
|
session_mgr_ = NULL;
|
|
fill_scanner_.reset();
|
|
ObVirtualTableScannerIterator::reset();
|
|
}
|
|
|
|
int ObAllVirtualSessionInfo::inner_get_next_row(ObNewRow *&row)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(session_mgr_)) {
|
|
ret = OB_NOT_INIT;
|
|
SERVER_LOG(WARN, "sessionMgr is NULL", K(ret));
|
|
} else {
|
|
if (!start_to_read_) {
|
|
if (OB_FAIL(fill_scanner_.init(allocator_,
|
|
&scanner_,
|
|
session_,
|
|
&cur_row_,
|
|
output_column_ids_,
|
|
schema_guard_))) {
|
|
SERVER_LOG(WARN, "init fill_scanner fail", K(ret));
|
|
} else if (OB_FAIL(session_mgr_->for_each_hold_session(fill_scanner_))) {
|
|
SERVER_LOG(WARN, "fill scanner fail", K(ret));
|
|
} else {
|
|
scanner_it_ = scanner_.begin();
|
|
start_to_read_ = true;
|
|
}
|
|
}
|
|
if (OB_SUCCESS == ret && start_to_read_) {
|
|
if (OB_FAIL(scanner_it_.get_next_row(cur_row_))) {
|
|
if (OB_UNLIKELY(OB_ITER_END != ret)) {
|
|
SERVER_LOG(WARN, "fail to get next row", K(ret));
|
|
}
|
|
} else {
|
|
row = &cur_row_;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObAllVirtualSessionInfo::FillScanner::operator()(
|
|
hash::HashMapPair<uint64_t, ObSQLSessionInfo *> &entry)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *sess_info = entry.second;
|
|
if (OB_UNLIKELY(NULL == scanner_
|
|
|| NULL == allocator_
|
|
|| NULL == cur_row_
|
|
|| NULL == cur_row_->cells_
|
|
|| NULL == sess_info
|
|
|| NULL == my_session_)) {
|
|
ret = OB_NOT_INIT;
|
|
SERVER_LOG(WARN,
|
|
"parameter or data member is NULL",
|
|
K(ret),
|
|
K(scanner_),
|
|
K(allocator_),
|
|
K(cur_row_),
|
|
K(sess_info),
|
|
K(my_session_));
|
|
} else if (OB_UNLIKELY(cur_row_->count_ < output_column_ids_.count())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
SERVER_LOG(WARN,
|
|
"cells count is less than output column count",
|
|
K(ret),
|
|
K(cur_row_->count_),
|
|
K(output_column_ids_.count()));
|
|
} else {
|
|
ObServer &server = ObServer::get_instance();
|
|
uint64_t cell_idx = 0;
|
|
char ip_buf[common::OB_IP_STR_BUFF];
|
|
char peer_buf[common::OB_IP_PORT_STR_BUFF];
|
|
char sql_id[common::OB_MAX_SQL_ID_LENGTH + 1];
|
|
//If you are in system tenant, you can see all thread.
|
|
if (true) {
|
|
ObSQLSessionInfo::LockGuard lock_guard(sess_info->get_thread_data_lock());
|
|
const int64_t col_count = output_column_ids_.count();
|
|
ObCharsetType default_charset = ObCharset::get_default_charset();
|
|
ObCollationType default_collation = ObCharset::get_default_collation(default_charset);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < col_count; ++i) {
|
|
uint64_t col_id = output_column_ids_.at(i);
|
|
switch(col_id) {
|
|
case ID: {
|
|
cur_row_->cells_[cell_idx].set_uint64(static_cast<uint64_t>(sess_info->get_sessid()));
|
|
break;
|
|
}
|
|
case USER: {
|
|
if (sess_info->get_is_deserialized()) {
|
|
// this is a tmp solution to avoid core when we execute 'show processlist'
|
|
// before we finally find the reason and resolve the bug. otherwise we cannot
|
|
// use this command in on-line cluster.
|
|
// see
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_user_name());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
}
|
|
break;
|
|
}
|
|
case TENANT: {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_effective_tenant_name());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
break;
|
|
}
|
|
case HOST: {
|
|
if (OB_FAIL(sess_info->get_peer_addr().ip_port_to_string(peer_buf, common::OB_IP_PORT_STR_BUFF))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
SERVER_LOG(WARN, "fail to get ip string", K(ret), K(sess_info->get_peer_addr()));
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(ObString::make_string(peer_buf));
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
}
|
|
break;
|
|
}
|
|
case DB_NAME: {
|
|
if (0 == sess_info->get_database_name().length()) {//session don't select database
|
|
cur_row_->cells_[cell_idx].set_varchar(ObString::make_string("NULL"));
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_database_name());
|
|
}
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
break;
|
|
}
|
|
case COMMAND: {
|
|
cur_row_->cells_[cell_idx].set_varchar(ObString::make_string(sess_info->get_mysql_cmd_str()));
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
break;
|
|
}
|
|
case SQL_ID: {
|
|
sess_info->get_cur_sql_id(sql_id, OB_MAX_SQL_ID_LENGTH + 1);
|
|
cur_row_->cells_[cell_idx].set_varchar(ObString::make_string(sql_id));
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
break;
|
|
}
|
|
case TIME: {
|
|
int64_t time_sec = (::oceanbase::common::ObTimeUtility::current_time() - sess_info->get_cur_state_start_time()) / 1000000;
|
|
cur_row_->cells_[cell_idx].set_int(time_sec);
|
|
break;
|
|
}
|
|
case STATE: {
|
|
cur_row_->cells_[cell_idx].set_varchar(ObString::make_string(sess_info->get_session_state_str()));
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
break;
|
|
}
|
|
case INFO: {
|
|
if (obmysql::COM_QUERY == sess_info->get_mysql_cmd() ||
|
|
obmysql::COM_STMT_EXECUTE == sess_info->get_mysql_cmd() ||
|
|
obmysql::COM_STMT_PREPARE == sess_info->get_mysql_cmd() ||
|
|
obmysql::COM_STMT_PREXECUTE == sess_info->get_mysql_cmd()) {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_current_query_string());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
}
|
|
break;
|
|
}
|
|
case SVR_IP: {
|
|
if (!server.get_self().ip_to_string(ip_buf, common::OB_IP_STR_BUFF)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
SERVER_LOG(WARN, "fail to get ip string", K(ret), K(server.get_self()));
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(ObString::make_string(ip_buf));
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
}
|
|
break;
|
|
}
|
|
case SVR_PORT: {
|
|
cur_row_->cells_[cell_idx].set_int(server.get_self().get_port());
|
|
break;
|
|
}
|
|
case SQL_PORT: {
|
|
cur_row_->cells_[cell_idx].set_int(GCONF.mysql_port);
|
|
break;
|
|
}
|
|
case PROXY_SESSID: {
|
|
if (ObBasicSessionInfo::VALID_PROXY_SESSID == sess_info->get_proxy_sessid()) {
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_uint64(sess_info->get_proxy_sessid());
|
|
}
|
|
break;
|
|
}
|
|
case MASTER_SESSID: {
|
|
if (ObBasicSessionInfo::INVALID_SESSID == sess_info->get_master_sessid()) {
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_uint64(sess_info->get_master_sessid());
|
|
}
|
|
break;
|
|
}
|
|
case USER_CLIENT_IP: {
|
|
if (sess_info->get_client_ip().empty()) {
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_client_ip());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
}
|
|
break;
|
|
}
|
|
case USER_HOST: {
|
|
if (sess_info->get_host_name().empty()) {
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_host_name());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
}
|
|
break;
|
|
}
|
|
case TRANS_ID: {
|
|
uint64_t tx_id = sess_info->get_tx_id();
|
|
cur_row_->cells_[cell_idx].set_uint64(tx_id);
|
|
break;
|
|
}
|
|
case THREAD_ID: {
|
|
cur_row_->cells_[cell_idx].set_uint64(
|
|
static_cast<uint64_t>(sess_info->get_thread_id()));
|
|
break;
|
|
}
|
|
case SSL_CIPHER: {
|
|
if (sess_info->get_ssl_cipher().empty()) {
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_ssl_cipher());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
}
|
|
break;
|
|
}
|
|
case TRACE_ID: {
|
|
if (obmysql::COM_QUERY == sess_info->get_mysql_cmd() ||
|
|
obmysql::COM_STMT_EXECUTE == sess_info->get_mysql_cmd() ||
|
|
obmysql::COM_STMT_PREPARE == sess_info->get_mysql_cmd() ||
|
|
obmysql::COM_STMT_PREXECUTE == sess_info->get_mysql_cmd()) {
|
|
int len = sess_info->get_current_trace_id().to_string(trace_id_, sizeof(trace_id_));
|
|
cur_row_->cells_[cell_idx].set_varchar(trace_id_, len);
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
} else {
|
|
// when cmd=Sleep, we don't want to display its last query trace id
|
|
// as it is weird, not the meaning for 'processlist'
|
|
cur_row_->cells_[cell_idx].set_null();
|
|
}
|
|
break;
|
|
}
|
|
case REF_COUNT: {
|
|
cur_row_->cells_[cell_idx].set_int(sess_info->get_sess_ref_cnt());
|
|
break;
|
|
}
|
|
case BACKTRACE: {
|
|
cur_row_->cells_[cell_idx].set_varchar(sess_info->get_sess_bt());
|
|
cur_row_->cells_[cell_idx].set_collation_type(default_collation);
|
|
break;
|
|
}
|
|
case TRANS_STATE: {
|
|
if (sess_info->is_in_transaction()) {
|
|
cur_row_->cells_[cell_idx].set_varchar(
|
|
sess_info->get_tx_desc()->get_tx_state_str());
|
|
} else {
|
|
cur_row_->cells_[cell_idx].set_varchar("");
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
SERVER_LOG(WARN, "invalid column id", K(ret), K(cell_idx),
|
|
K(i), K(output_column_ids_), K(col_id));
|
|
break;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
cell_idx++;
|
|
}
|
|
} // for
|
|
if (OB_UNLIKELY(OB_SUCCESS == ret && OB_SUCCESS != (ret = scanner_->add_row(*cur_row_)))) {
|
|
SERVER_LOG(WARN, "fail to add row", K(ret), K(*cur_row_));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObAllVirtualSessionInfo::FillScanner::reset()
|
|
{
|
|
allocator_ = NULL;
|
|
scanner_ = NULL;
|
|
cur_row_ = NULL;
|
|
my_session_ = NULL;
|
|
trace_id_[0] = '\0';
|
|
output_column_ids_.reset();
|
|
}
|
|
|
|
int ObAllVirtualSessionInfo::FillScanner::init(ObIAllocator *allocator,
|
|
common::ObScanner *scanner,
|
|
sql::ObSQLSessionInfo *session_info,
|
|
common::ObNewRow *cur_row,
|
|
const ObIArray<uint64_t> &column_ids,
|
|
share::schema::ObSchemaGetterGuard* schema_guard)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(NULL == allocator
|
|
|| NULL == scanner
|
|
|| NULL == cur_row
|
|
|| NULL == session_info)) {
|
|
ret = OB_NOT_INIT;
|
|
SERVER_LOG(WARN,
|
|
"some parameter is NULL", K(ret), K(allocator), K(scanner), K(cur_row), K(session_info));
|
|
} else if (OB_FAIL(output_column_ids_.assign(column_ids))) {
|
|
SQL_ENG_LOG(WARN, "fail to assign output column ids", K(ret), K(column_ids));
|
|
} else {
|
|
allocator_ = allocator;
|
|
scanner_ = scanner;
|
|
cur_row_ = cur_row;
|
|
my_session_ = session_info;
|
|
schema_guard_ = schema_guard;
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
}/* ns observer*/
|
|
}/* ns oceanbase */
|