Files
oceanbase/src/observer/virtual_table/ob_virtual_span_info.cpp
2023-04-28 02:41:45 +00:00

407 lines
14 KiB
C++

/*
* Copyright (c) 2022 OceanBase Technology Co.,Ltd.
* OceanBase is licensed under Mulan PubL v1.
* You can use this software according to the terms and conditions of the Mulan PubL v1.
* You may obtain a copy of Mulan PubL v1 at:
* http://license.coscl.org.cn/MulanPubL-1.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 v1 for more details.
* ---------------------------------------------------------------------------------------
* Authors:
* Juehui <>
* ---------------------------------------------------------------------------------------
*/
#include "observer/virtual_table/ob_virtual_span_info.h"
#include "sql/monitor/flt/ob_flt_span_mgr.h"
#include "sql/session/ob_sql_session_info.h"
#include "observer/omt/ob_multi_tenant.h"
using namespace oceanbase::common;
using namespace oceanbase::obmysql;
using namespace oceanbase::omt;
using namespace oceanbase::share;
namespace oceanbase {
namespace observer {
ObVirtualSpanInfo::ObVirtualSpanInfo() :
ObVirtualTableScannerIterator(),
cur_flt_span_mgr_(nullptr),
start_id_(INT64_MAX),
end_id_(INT64_MIN),
cur_id_(0),
ref_(),
addr_(NULL),
ipstr_(),
port_(0),
is_first_get_(true),
with_tenant_ctx_(nullptr)
{
}
ObVirtualSpanInfo::~ObVirtualSpanInfo() {
reset();
}
void ObVirtualSpanInfo::reset()
{
if (cur_flt_span_mgr_ != nullptr && ref_.idx_ != -1) {
cur_flt_span_mgr_->revert(&ref_);
}
ObVirtualTableScannerIterator::reset();
is_first_get_ = true;
cur_id_ = 0;
start_id_ = INT64_MAX;
end_id_ = INT64_MIN;
cur_flt_span_mgr_ = nullptr;
addr_ = nullptr;
port_ = 0;
ipstr_.reset();
}
int ObVirtualSpanInfo::inner_open()
{
int ret = OB_SUCCESS;
if (OB_SUCC(ret)) {
if (NULL == allocator_) {
ret = OB_INVALID_ARGUMENT;
SERVER_LOG(WARN, "Invalid Allocator", K(ret));
} else if (OB_FAIL(set_ip(addr_))) {
SERVER_LOG(WARN, "failed to set server ip addr", K(ret));
} else {
// do nothing
}
}
return ret;
}
int ObVirtualSpanInfo::set_ip(common::ObAddr *addr)
{
int ret = OB_SUCCESS;
MEMSET(server_ip_, 0, sizeof(server_ip_));
if (NULL == addr){
ret = OB_ENTRY_NOT_EXIST;
} else if (!addr_->ip_to_string(server_ip_, sizeof(server_ip_))) {
SERVER_LOG(ERROR, "ip to string failed");
ret = OB_ERR_UNEXPECTED;
} else {
ipstr_ = ObString::make_string(server_ip_);
port_ = addr_->get_port();
}
return ret;
}
int ObVirtualSpanInfo::inner_get_next_row(common::ObNewRow *&row)
{
int ret = OB_SUCCESS;
if (NULL == allocator_) {
ret = OB_NOT_INIT;
SERVER_LOG(WARN, "invalid argument", KP(allocator_), K(ret));
} else if (is_first_get_) {
bool is_valid = true;
cur_flt_span_mgr_ = nullptr;
if (OB_FAIL(check_ip_and_port(is_valid))) {
SERVER_LOG(WARN, "check ip and port failed", K(ret));
} else if (!is_valid) {
ret = OB_ITER_END;;
}
}
if (OB_SUCC(ret)) {
if (nullptr == cur_flt_span_mgr_) {
cur_flt_span_mgr_ = nullptr;
uint64_t t_id = effective_tenant_id_;
cur_flt_span_mgr_ = MTL(sql::ObFLTSpanMgr*);
if (nullptr == cur_flt_span_mgr_) {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "req manager doest not exist", K(t_id));
} else if (OB_SUCC(ret)) {
start_id_ = cur_flt_span_mgr_->get_start_idx();
end_id_ = cur_flt_span_mgr_->get_end_idx();
if (start_id_ >= end_id_) {
// iter end do nothing
} else {
cur_id_ = start_id_;
}
SERVER_LOG(TRACE, "start to get rows from virtual span info",
K(start_id_), K(end_id_), K(cur_id_), K(t_id));
}
}
if (cur_id_ < start_id_ || cur_id_ >= end_id_) {
ret = OB_ITER_END;
SERVER_LOG(INFO, "scan finished", K(start_id_), K(end_id_), K(cur_id_));
}
// if has no more record, free current flt span manager
if (OB_ITER_END == ret) {
if (cur_flt_span_mgr_ != nullptr && ref_.idx_ != -1) {
cur_flt_span_mgr_->revert(&ref_);
}
}
}
if (OB_SUCC(ret)) {
void *rec = NULL;
if (ref_.idx_ != -1) {
cur_flt_span_mgr_->revert(&ref_);
}
do {
ref_.reset();
if (OB_ENTRY_NOT_EXIST == (ret = cur_flt_span_mgr_->get(cur_id_, rec, &ref_))) {
cur_id_ += 1;
}
} while (OB_ENTRY_NOT_EXIST == ret && cur_id_ < end_id_ && cur_id_ >= start_id_);
if (OB_SUCC(ret)) {
if (NULL != rec) {
sql::ObFLTSpanRec *record = static_cast<sql::ObFLTSpanRec*> (rec);
if (OB_FAIL(fill_cells(*record))) {
SERVER_LOG(WARN, "failed to fill cells", K(ret));
} else {
//finish fetch one row
row = &cur_row_;
SERVER_LOG(TRACE, "request_info_table get next row succ", K(cur_id_), K(cur_row_));
}
} else {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "unexpected null rec",
K(rec), K(cur_id_), K(ret));
}
}
is_first_get_ = false;
// move to next slot
if (OB_SUCC(ret)) {
cur_id_++;
}
}
return ret;
}
int ObVirtualSpanInfo::fill_cells(sql::ObFLTSpanRec &record)
{
int ret = OB_SUCCESS;
const int64_t col_count = output_column_ids_.count();
ObObj *cells = cur_row_.cells_;
if (OB_ISNULL(cells)) {
ret = OB_INVALID_ARGUMENT;
SERVER_LOG(WARN, "invalid argument", K(cells));
} else {
for (int64_t cell_idx = 0; OB_SUCC(ret) && cell_idx < col_count; cell_idx++) {
uint64_t col_id = output_column_ids_.at(cell_idx);
switch(col_id) {
//server ip
case SVR_IP: {
cells[cell_idx].set_varchar(ipstr_); //ipstr_ and port_ were set in set_ip func call
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
//server port
case SVR_PORT: {
cells[cell_idx].set_int(port_);
} break;
case TENANT_ID: {
cells[cell_idx].set_int(record.data_.tenant_id_);
} break;
case TRACE_ID: {
cells[cell_idx].set_varchar(record.data_.trace_id_);
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
case REQUEST_ID: {
cells[cell_idx].set_int(record.data_.req_id_);
} break;
case SPAN_ID: {
cells[cell_idx].set_varchar(record.data_.span_id_);
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
case PARENT_SPAN_ID: {
cells[cell_idx].set_varchar(record.data_.parent_span_id_);
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
case SPAN_NAME: {
cells[cell_idx].set_varchar(record.data_.span_name_);
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
case REF_TYPE: {
if (record.data_.ref_type_ == 0) {
cells[cell_idx].set_varchar("CHILD");
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} else if (record.data_.ref_type_ == 1) {
cells[cell_idx].set_varchar("FOLLOW");
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} else {
// do nothing
}
} break;
case START_TS: {
cells[cell_idx].set_int(record.data_.start_ts_);
} break;
case END_TS: {
cells[cell_idx].set_int(record.data_.end_ts_);
} break;
case TAGS: {
cells[cell_idx].set_lob_value(ObLongTextType,
record.data_.tags_.ptr(),
record.data_.tags_.length());
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
case LOGS: {
cells[cell_idx].set_lob_value(ObLongTextType,
record.data_.logs_.ptr(),
record.data_.logs_.length());
cells[cell_idx].set_collation_type(ObCharset::get_default_collation(
ObCharset::get_default_charset()));
} break;
default: {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "invalid column id", K(ret), K(cell_idx), K(col_id));
} break;
}
}
}
return ret;
}
int ObVirtualSpanInfo::extract_request_ids(const uint64_t tenant_id,
int64_t &start_id,
int64_t &end_id,
bool &is_valid)
{
int ret = OB_SUCCESS;
is_valid = true;
const int64_t req_id_key_idx = PRI_KEY_REQ_ID_IDX;
const int64_t tenant_id_key_idx = PRI_KEY_TENANT_ID_IDX;
if (key_ranges_.count() >= 1) {
for (int i = 0; OB_SUCC(ret) && is_valid && i < key_ranges_.count(); i++) {
ObNewRange &req_id_range = key_ranges_.at(i);
SERVER_LOG(DEBUG, "extracting request id for tenant", K(req_id_range), K(tenant_id));
if (OB_UNLIKELY(req_id_range.get_start_key().get_obj_cnt() != 4
|| req_id_range.get_end_key().get_obj_cnt() != 4)
|| OB_ISNULL(req_id_range.get_start_key().get_obj_ptr())
|| OB_ISNULL(req_id_range.get_end_key().get_obj_ptr())) {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "unexpected # of rowkey columns",
K(ret),
"size of start key", req_id_range.get_start_key().get_obj_cnt(),
"size of end key", req_id_range.get_end_key().get_obj_cnt(),
K(req_id_range.get_start_key().get_obj_ptr()),
K(req_id_range.get_end_key().get_obj_ptr()));
} else {
const ObObj &tenant_obj_high = req_id_range.get_end_key().get_obj_ptr()[tenant_id_key_idx];
const ObObj &tenant_obj_low = req_id_range.get_start_key().get_obj_ptr()[tenant_id_key_idx];
uint64_t min_tenant_id = 0;
uint64_t max_tenant_id = 0;
if (tenant_obj_low.is_min_value()) {
min_tenant_id = 0;
} else if (tenant_obj_low.is_max_value()) {
min_tenant_id = UINT64_MAX;
} else {
min_tenant_id = tenant_obj_low.get_uint64();
}
if (tenant_obj_high.is_min_value()) {
max_tenant_id = 0;
} else if (tenant_obj_high.is_max_value()) {
max_tenant_id = UINT64_MAX;
} else {
max_tenant_id = tenant_obj_high.get_uint64();
}
if (min_tenant_id <= max_tenant_id
&& min_tenant_id <= tenant_id
&& max_tenant_id >= tenant_id) {
const ObObj &cur_start = req_id_range.get_start_key().get_obj_ptr()[req_id_key_idx];
const ObObj &cur_end = req_id_range.get_end_key().get_obj_ptr()[req_id_key_idx];
int64_t cur_start_id = -1;
int64_t cur_end_id = -1;
if (cur_start.is_min_value()) {
cur_start_id = 0;
} else if (cur_start.is_max_value()) {
cur_start_id = INT64_MAX;
} else {
cur_start_id = cur_start.get_int();
}
if (cur_end.is_min_value()) {
cur_end_id = 0;
} else if (cur_end.is_max_value()) {
cur_end_id = INT64_MAX;
} else {
cur_end_id = cur_end.get_int() + 1;
}
if (0 == i) {
start_id = cur_start_id;
end_id = cur_end_id;
if (start_id >= end_id) {
is_valid = false;
}
} else {
start_id = MIN(cur_start_id, start_id);
end_id = MAX(cur_end_id, end_id);
if (start_id >= end_id) {
is_valid = false;
}
}
}
}
}
}
return ret;
}
int ObVirtualSpanInfo::check_ip_and_port(bool &is_valid)
{
int ret = OB_SUCCESS;
is_valid = true;
// is_serving_tenant被改成 (svr_ip, svr_port) in (ip1, port1), (ip2, port2), ...
// 抽出来的query range为[(ip1, port1), (ip1, port1)], [(ip2, port2), (ip2, port2)], ...
// 需要遍历所有query range,判断本机的ip & port是否落在某一个query range中
if (key_ranges_.count() >= 1) {
is_valid = false;
for (int64_t i = 0; OB_SUCC(ret) && !is_valid && i < key_ranges_.count(); i++) {
ObNewRange &req_id_range = key_ranges_.at(i);
if (OB_UNLIKELY(req_id_range.get_start_key().get_obj_cnt() != 4
|| req_id_range.get_end_key().get_obj_cnt() != 4)) {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "unexpected # of rowkey columns",
K(ret),
"size of start key", req_id_range.get_start_key().get_obj_cnt(),
"size of end key", req_id_range.get_end_key().get_obj_cnt());
} else {
ObObj ip_obj;
ObObj ip_low = (req_id_range.get_start_key().get_obj_ptr()[PRI_KEY_IP_IDX]);
ObObj ip_high = (req_id_range.get_end_key().get_obj_ptr()[PRI_KEY_IP_IDX]);
ip_obj.set_varchar(ipstr_);
ip_obj.set_collation_type(ip_low.get_collation_type());
if (ip_obj.compare(ip_low) >= 0 && ip_obj.compare(ip_high) <= 0) {
ObObj port_obj;
port_obj.set_int32(port_);
ObObj port_low = (req_id_range.get_start_key().get_obj_ptr()[PRI_KEY_PORT_IDX]);
ObObj port_high = (req_id_range.get_end_key().get_obj_ptr()[PRI_KEY_PORT_IDX]);
if (port_obj.compare(port_low) >= 0 && port_obj.compare(port_high) <= 0) {
is_valid = true;
}
} else {
// do nothing
}
}
}
}
SERVER_LOG(DEBUG, "check ip and port", K(key_ranges_), K(is_valid), K(ipstr_), K(port_));
return ret;
}
} //namespace observer
} //namespace oceanbase