2
* Copyright (c) 2021 OceanBase
3
* OceanBase CE is licensed under Mulan PubL v2.
4
* You can use this software according to the terms and conditions of the Mulan PubL v2.
5
* You may obtain a copy of Mulan PubL v2 at:
6
* http://license.coscl.org.cn/MulanPubL-2.0
7
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
* See the Mulan PubL v2 for more details.
13
#include "ob_lua_api.h"
14
#include "ob_lua_handler.h"
21
#include "lib/alloc/memory_dump.h"
22
#include "lib/allocator/ob_mem_leak_checker.h"
23
#include "lib/oblog/ob_log.h"
24
#include "lib/stat/ob_di_cache.h"
25
#include "observer/omt/ob_multi_tenant.h"
26
#include "observer/omt/ob_tenant.h"
27
#include "observer/virtual_table/ob_all_virtual_sys_stat.h"
28
#include "share/inner_table/ob_inner_table_schema.h"
29
#include "share/ob_tenant_mgr.h"
30
#include "share/scheduler/ob_dag_warning_history_mgr.h"
31
#include "share/scheduler/ob_sys_task_stat.h"
32
#include "storage/compaction/ob_compaction_diagnose.h"
33
#include "storage/memtable/ob_lock_wait_mgr.h"
34
#include "storage/tx/ob_trans_ctx_mgr_v4.h"
35
#include "storage/tx/ob_trans_service.h"
36
#include "storage/tx/ob_tx_stat.h"
37
#include "observer/ob_server.h"
38
#include "rpc/obrpc/ob_rpc_packet.h"
39
#include "rpc/obrpc/ob_rpc_stat.h"
40
#include "sql/session/ob_sql_session_info.h"
41
#include "sql/engine/ob_tenant_sql_memory_manager.h"
45
using namespace oceanbase;
46
using namespace common;
47
using namespace diagnose;
48
using namespace oceanbase::observer;
49
using namespace oceanbase::rpc::frame;
53
using namespace transaction;
59
class LuaAllocator : public ObIAllocator
62
static LuaAllocator& get_instance()
64
static LuaAllocator allocator;
67
void *alloc(const int64_t size) override
70
if (0 != size && ObLuaHandler::get_instance().memory_usage() + size + 8 < ObLuaHandler::LUA_MEMORY_LIMIT) {
71
#if defined(OB_USE_ASAN) || defined(ENABLE_SANITY)
72
if (OB_NOT_NULL(ret = ::malloc(size + 8))) {
74
if (MAP_FAILED == (ret = ::mmap(nullptr, size + 8, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))) {
78
*static_cast<uint64_t *>(ret) = size;
80
ObLuaHandler::get_instance().memory_update(size + 8);
85
void* alloc(const int64_t size, const ObMemAttr &attr) override
90
void free(void *ptr) override
92
if (OB_NOT_NULL(ptr)) {
93
const uint64_t size = *(uint64_t *)((char *)ptr - 8);
94
ObLuaHandler::get_instance().memory_update(- 8 - size);
95
#if defined(OB_USE_ASAN) || defined(ENABLE_SANITY)
96
::free((void *)((char *)ptr - 8));
98
::munmap((void *)((char *)ptr - 8), size + 8);
105
static ObFIFOAllocator &get_global_allocator()
107
static ObFIFOAllocator allocator;
108
if (OB_UNLIKELY(!allocator.is_inited())) {
109
IGNORE_RETURN allocator.init(&LuaAllocator::get_instance(), (1 << 13) - 8, lib::ObMemAttr(OB_SERVER_TENANT_ID, "LuaAlloc"), 0, 0, INT64_MAX);
115
static constexpr const char *usage_str =
118
"print_to_client(arg1, arg2...)\n"
120
"{int, int, ...} = get_tenant_id_list()\n"
121
"int = get_tenant_mem_limit(int)\n"
122
"int = get_tenant_sysstat_by_id(int, int)\n"
123
"int = get_tenant_sysstat_by_name(int, string)\n"
124
"string = get_easy_diagnose_info()\n"
125
"string = get_tenant_pcode_statistics(int, int)\n"
126
"{{row1}, {row2}, ...} = select_processlist()\n"
127
"{{row1}, {row2}, ...} = select_sysstat()\n"
128
"{{row1}, {row2}, ...} = select_memory_info()\n"
129
"{{row1}, {row2}, ...} = select_tenant_ctx_memory_info()\n"
130
"{{row1}, {row2}, ...} = select_trans_stat()\n"
131
"{{row1}, {row2}, ...} = select_sql_workarea_active()\n"
132
"{{row1}, {row2}, ...} = select_sys_task_status()\n"
133
"{{row1}, {row2}, ...} = select_dump_tenant_info()\n"
134
"{{row1}, {row2}, ...} = select_disk_stat()\n"
135
"{{row1}, {row2}, ...} = select_tenant_memory_info()\n"
136
"string = show_log_probe()\n"
137
"int = set_log_probe(string)\n"
138
"{{row1}, {row2}, ...} = select_mem_leak_checker_info()\n"
139
"{{row1}, {row2}, ...} = select_compaction_diagnose_info()\n"
140
"{{row1}, {row2}, ...} = select_server_schema_info()\n"
141
"{{row1}, {row2}, ...} = select_schema_slot()\n"
142
"{{row1}, {row2}, ...} = dump_thread_info()\n"
143
"{{row1}, {row2}, ...} = select_malloc_sample_info()\n"
144
"int = set_system_tenant_limit_mode(int)\n"
147
class LuaVtableGenerator
150
LuaVtableGenerator(lua_State* L, std::vector<const char*>& columns)
154
offset_(0), // dump from first row by default
155
length_(INT_MAX), // dump all rows by default
160
select_.set(); // enable all column by default
161
if (1 == lua_gettop(stack_)) {
167
lua_newtable(stack_);
172
if (row_id_ >= offset_ && row_id_ - offset_ < length_) {
174
lua_pushinteger(stack_, row_id_ + 1);
175
lua_newtable(stack_);
181
if (row_id_ >= offset_ && row_id_ - offset_ < length_) {
183
lua_settable(stack_, -3);
185
int ret = OB_SUCCESS;
186
if (OB_FAIL(APIRegister::get_instance().append("\n"))) {
187
OB_LOG(ERROR, "append failed", K(ret));
198
lua_pushstring(stack_, columns_[column_id_]);
200
lua_settable(stack_, -3);
202
int ret = OB_SUCCESS;
203
if (OB_FAIL(APIRegister::get_instance().append("NULL "))) {
204
OB_LOG(ERROR, "append failed", K(ret));
209
void next_column(const char* str)
213
lua_pushstring(stack_, columns_[column_id_]);
214
lua_pushstring(stack_, str);
215
lua_settable(stack_, -3);
217
int ret = OB_SUCCESS;
218
if (OB_FAIL(APIRegister::get_instance().append(str))) {
219
OB_LOG(ERROR, "append failed", K(ret));
221
if (OB_FAIL(APIRegister::get_instance().append(" "))) {
222
OB_LOG(ERROR, "append failed", K(ret));
227
void next_column(bool value)
231
lua_pushstring(stack_, columns_[column_id_]);
232
lua_pushboolean(stack_, value);
233
lua_settable(stack_, -3);
235
int ret = OB_SUCCESS;
236
if (OB_FAIL(APIRegister::get_instance().append(value ? "1 " : "0 "))) {
237
OB_LOG(ERROR, "append failed", K(ret));
242
void next_column(int64_t value)
246
lua_pushstring(stack_, columns_[column_id_]);
247
lua_pushinteger(stack_, value);
248
lua_settable(stack_, -3);
250
int ret = OB_SUCCESS;
252
snprintf(buf, 32, "%ld ", value);
253
if (OB_FAIL(APIRegister::get_instance().append(buf))) {
254
OB_LOG(ERROR, "append failed", K(ret));
259
void next_column(double value)
263
lua_pushstring(stack_, columns_[column_id_]);
264
lua_pushnumber(stack_, value);
265
lua_settable(stack_, -3);
267
int ret = OB_SUCCESS;
269
snprintf(buf, 32, "%lf ", value);
270
if (OB_FAIL(APIRegister::get_instance().append(buf))) {
271
OB_LOG(ERROR, "append failed", K(ret));
276
void next_column(uint64_t value)
278
next_column((int64_t)value);
280
void next_column(int32_t value)
282
next_column((int64_t)value);
284
void next_column(uint32_t value)
286
next_column((int64_t)value);
290
return row_id_ - offset_ >= length_;
295
luaL_checktype(stack_, -1, LUA_TTABLE);
297
while (lua_next(stack_, -2) != 0) {
298
luaL_checktype(stack_, -2, LUA_TSTRING);
299
const char *key = lua_tostring(stack_, -2);
300
if (0 == strcmp(key, "select")) {
301
luaL_checktype(stack_, -1, LUA_TTABLE);
304
while (lua_next(stack_, -2) != 0) {
305
luaL_checktype(stack_, -1, LUA_TSTRING);
306
const char *column_name = lua_tostring(stack_, -1);
307
for (auto i = 0; i < columns_.size(); ++i) {
308
if (0 == strcmp(columns_[i], column_name)) {
314
} else if (0 == strcmp(key, "limit")) {
315
luaL_checktype(stack_, -1, LUA_TTABLE);
317
if (lua_next(stack_, -2) != 0) {
318
offset_ = lua_tointeger(stack_, -1);
320
if (lua_next(stack_, -2) != 0) {
321
length_ = lua_tointeger(stack_, -1);
328
} else if (0 == strcmp(key, "dump")) {
329
luaL_checktype(stack_, -1, LUA_TBOOLEAN);
330
if (0 != lua_toboolean(stack_, -1)) {
334
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "invalid arguments", K(key));
342
return row_id_ >= offset_ && row_id_ - offset_ < length_ && select_[++column_id_];
351
std::bitset<256> select_;
352
std::vector<const char*>& columns_;
356
* All API need to use the following format.
357
* int xxx(lua_State* L), which return the count of return values.
359
* lua API for reference: http://www.lua.org/manual/5.4/
363
int usage(lua_State* L)
365
int argc = lua_gettop(L);
367
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call usage() failed, bad arguments count, should be 0.");
370
lua_pushstring(L, usage_str);
375
// print_to_client(arg1, arg2...)
376
int print_to_client(lua_State* L)
378
int nargs = lua_gettop(L);
379
for (int i = 1; i <= nargs; i++) {
380
int ret = OB_SUCCESS;
381
if (lua_isinteger(L, i) || lua_isstring(L, i) || lua_isnumber(L, i)) {
383
const char *arg = lua_tolstring(L, i, &len);
384
if (OB_FAIL(APIRegister::get_instance().append(arg, len))) {
385
OB_LOG(ERROR, "append failed", K(ret), K(len));
387
} else if (lua_isboolean(L, i)) {
388
if (0 == lua_toboolean(L, i)) {
389
if (OB_FAIL(APIRegister::get_instance().append("0"))) {
390
OB_LOG(ERROR, "append failed", K(ret));
393
if (OB_FAIL(APIRegister::get_instance().append("1"))) {
394
OB_LOG(ERROR, "append failed", K(ret));
397
} else if (lua_islightuserdata(L, i)) {
398
void *ptr = lua_touserdata(L, i);
400
snprintf(buf, sizeof(buf), "%p", ptr);
401
if (OB_FAIL(APIRegister::get_instance().append(buf))) {
402
OB_LOG(ERROR, "append failed", K(ret));
404
} else if (lua_isnil(L, i)) {
405
ret = APIRegister::get_instance().append("NULL");
407
OB_LOG(ERROR, "arg was not convertible", K(i));
409
APIRegister::get_instance().append(" ");
411
APIRegister::get_instance().append("\n");
418
int argc = lua_gettop(L);
420
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call get_tenant_id_list() failed, bad arguments count, should be 0.");
421
lua_pushinteger(L, 0);
423
lua_pushinteger(L, common::ObTimeUtility::fast_current_time());
428
// list = get_tenant_id_list()
429
int get_tenant_id_list(lua_State* L)
431
int argc = lua_gettop(L);
433
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call get_tenant_id_list() failed, bad arguments count, should be 0.");
436
uint64_t *tenant_ids = nullptr;
438
if (OB_NOT_NULL(tenant_ids = (uint64_t *)diagnose::alloc(OB_MAX_SERVER_TENANT_CNT * sizeof(uint64_t)))) {
439
get_tenant_ids(tenant_ids, OB_MAX_SERVER_TENANT_CNT, count);
441
for (int64_t i = 0; i < count; ++i) {
442
lua_pushinteger(L, i + 1);
443
lua_pushinteger(L, tenant_ids[i]);
446
diagnose::free(tenant_ids);
451
// int = get_tenant_mem_limit(int)
452
int get_tenant_mem_limit(lua_State* L)
454
int argc = lua_gettop(L);
456
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call get_tenant_mem_limit() failed, bad arguments count, should be 1.");
458
luaL_checktype(L, 1, LUA_TNUMBER);
459
lua_pushinteger(L, ObMallocAllocator::get_instance()->get_tenant_limit(lua_tointeger(L, 1)));
464
int get_tenant_parameter(lua_State* L)
471
// forward declaration
472
int get_tenant_sysstat(int64_t tenant_id, int64_t stat_id, int64_t &value);
474
// int = get_tenant_sysstat_by_id(int, int)
475
int get_tenant_sysstat_by_id(lua_State* L)
477
int ret = OB_SUCCESS;
478
int argc = lua_gettop(L);
480
OB_LOG(ERROR, "call get_tenant_sysstat_by_id() failed, bad arguments count, should be 2.");
481
ret = OB_INVALID_ARGUMENT;
483
luaL_checktype(L, 1, LUA_TNUMBER);
484
luaL_checktype(L, 2, LUA_TNUMBER);
485
int tenant_id = lua_tointeger(L, 1);
486
int stat_id = lua_tointeger(L, 2);
488
for (int i = 0; i < ObStatEventIds::STAT_EVENT_SET_END; ++i) {
489
if (OB_STAT_EVENTS[i].stat_id_ == stat_id) {
490
if (OB_FAIL(get_tenant_sysstat(tenant_id, i, value))) {
491
OB_LOG(ERROR, "failed to get tenant diag info", K(ret), K(tenant_id), K(i), K(stat_id));
493
lua_pushinteger(L, value);
505
// int = get_tenant_sysstat_by_name(int, string)
506
int get_tenant_sysstat_by_name(lua_State* L)
508
int ret = OB_SUCCESS;
509
int argc = lua_gettop(L);
511
OB_LOG(ERROR, "call get_tenant_sysstat_by_name() failed, bad arguments count, should be 2.");
512
ret = OB_INVALID_ARGUMENT;
514
luaL_checktype(L, 1, LUA_TNUMBER);
515
luaL_checktype(L, 2, LUA_TSTRING);
516
int tenant_id = lua_tointeger(L, 1);
517
const char *name = lua_tostring(L, 2);
519
ret = OB_ENTRY_NOT_EXIST;
520
for (int i = 0; i < ObStatEventIds::STAT_EVENT_SET_END; ++i) {
521
if (0 == strcmp(OB_STAT_EVENTS[i].name_, name)) {
522
if (OB_FAIL(get_tenant_sysstat(tenant_id, i, value))) {
523
OB_LOG(ERROR, "failed to get tenant diag info", K(ret), K(tenant_id), K(i), K(name));
525
lua_pushinteger(L, value);
537
int summary_each_eio_info(char *buf, int &pos, int buf_len, easy_io_t *eio, const char *rpc_des);
539
int get_easy_diagnose_info(lua_State* L)
541
int ret = OB_SUCCESS;
542
easy_io_t *eio = NULL;
543
ObNetEasy *net_easy = ObServer::get_instance().get_net_frame().get_net_easy();
544
if (NULL == net_easy) {
548
const int summary_len = 48 * 1024;
549
HEAP_VAR(ByteBuf<summary_len>, summary) {
550
memset(summary, 0, sizeof(summary));
552
eio = net_easy->get_rpc_eio();
553
ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "rpc_eio:\n");
555
eio = net_easy->get_batch_rpc_eio();
557
ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "batch_rpc_eio:\n");
560
eio = net_easy->get_high_prio_eio();
562
ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "high_prio_rpc_eio:\n");
565
eio = net_easy->get_mysql_eio();
567
ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "my_sql_rpc_eio:\n");
570
lua_pushstring(L, (const char*) summary);
577
int get_tenant_pcode_statistics(lua_State* L)
579
int ret = OB_SUCCESS;
580
int argc = lua_gettop(L);
582
OB_LOG(ERROR, "call get_tenant_pcode_statistics() failed, bad arguments count, should be 1.");
583
ret = OB_INVALID_ARGUMENT;
585
luaL_checktype(L, 1, LUA_TNUMBER);
586
int tenant_id = lua_tointeger(L, 1);
587
ObRpcPacketSet &set = ObRpcPacketSet::instance();
589
char *pcode_name = nullptr;
591
HEAP_VAR(ByteBuf<64 * ObRpcPacketSet::THE_PCODE_COUNT>, output) {
594
for (int64_t pcode_idx = 0; pcode_idx < ObRpcPacketSet::THE_PCODE_COUNT; pcode_idx++) {
595
if (OB_FAIL(RPC_STAT_GET(pcode_idx, tenant_id, item))) {
597
} else if (item.dcount_ != 0) {
598
pcode_name = const_cast<char*>(set.name_of_idx(pcode_idx));
599
snprintf(str, sizeof(str), "pcode_name:%s, count:%ld\n", pcode_name, item.dcount_);
600
strncpy(output + pos, str, strlen(str));
604
lua_pushstring(L, (const char*)output);
613
// int = set_log_probe(string)
614
int set_log_probe(lua_State* L)
616
int ret = OB_SUCCESS;
617
int argc = lua_gettop(L);
619
OB_LOG(ERROR, "call set_log_probe() failed, bad arguments count, should be 1.");
620
ret = OB_INVALID_ARGUMENT;
622
luaL_checktype(L, 1, LUA_TSTRING);
624
const char *arg = lua_tolstring(L, 1, &len);
625
char *ptr = (char*)diagnose::alloc(len + 1);
626
DEFER(if (ptr) diagnose::free(ptr););
627
if (OB_ISNULL(ptr)) {
628
ret = OB_ALLOCATE_MEMORY_FAILED;
629
OB_LOG(ERROR, "alloc memory failed", K(len));
631
memcpy(ptr, arg, len);
633
int probe_cnt = OB_LOGGER.set_probe(ptr);
634
lua_pushinteger(L, probe_cnt);
638
lua_pushinteger(L, -1);
643
// string = show_log_probe()
644
int show_log_probe(lua_State* L)
646
int argc = lua_gettop(L);
648
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call show_log_probe() failed, bad arguments count, should be 0.");
650
lua_pushstring(L, OB_LOGGER.show_probe());
655
// list{list, list...} = select_processlist()
656
int select_processlist(lua_State* L)
661
GetProcess(LuaVtableGenerator& gen) : gen_(gen) {}
662
bool operator()(sql::ObSQLSessionMgr::Key key, ObSQLSessionInfo *sess_info)
664
constexpr int64_t BUF_LEN = (1 << 10);
668
gen_.next_column(static_cast<uint64_t>(key.sessid_));
670
if (sess_info->get_is_deserialized()) {
673
UNUSED(sess_info->get_user_name().to_string(buf, BUF_LEN));
674
gen_.next_column(buf);
677
UNUSED(sess_info->get_tenant_name().to_string(buf, BUF_LEN));
678
gen_.next_column(buf);
680
UNUSED(sess_info->get_peer_addr().ip_port_to_string(buf, BUF_LEN));
681
gen_.next_column(buf);
683
if (0 == sess_info->get_database_name().length()) {
686
UNUSED(sess_info->get_database_name().to_string(buf, BUF_LEN));
687
gen_.next_column(buf);
690
gen_.next_column(sess_info->get_mysql_cmd_str());
693
char sql_id[common::OB_MAX_SQL_ID_LENGTH + 1];
694
if (obmysql::COM_QUERY == sess_info->get_mysql_cmd() ||
695
obmysql::COM_STMT_EXECUTE == sess_info->get_mysql_cmd() ||
696
obmysql::COM_STMT_PREPARE == sess_info->get_mysql_cmd() ||
697
obmysql::COM_STMT_PREXECUTE == sess_info->get_mysql_cmd()) {
698
sess_info->get_cur_sql_id(sql_id, OB_MAX_SQL_ID_LENGTH + 1);
702
gen_.next_column(sql_id);
705
gen_.next_column((::oceanbase::common::ObTimeUtility::current_time() - sess_info->get_cur_state_start_time()) / 1000000);
707
gen_.next_column(sess_info->get_session_state_str());
709
if (obmysql::COM_QUERY == sess_info->get_mysql_cmd() ||
710
obmysql::COM_STMT_EXECUTE == sess_info->get_mysql_cmd() ||
711
obmysql::COM_STMT_PREPARE == sess_info->get_mysql_cmd() ||
712
obmysql::COM_STMT_PREXECUTE == sess_info->get_mysql_cmd()) {
713
UNUSED(sess_info->get_current_query_string().to_string(buf, BUF_LEN));
714
gen_.next_column(buf);
719
gen_.next_column(GCONF.mysql_port);
721
if (ObBasicSessionInfo::VALID_PROXY_SESSID == sess_info->get_proxy_sessid()) {
724
gen_.next_column(sess_info->get_proxy_sessid());
727
if (ObBasicSessionInfo::INVALID_SESSID == sess_info->get_master_sessid()) {
730
gen_.next_column(sess_info->get_master_sessid());
733
if (sess_info->get_client_ip().empty()) {
736
UNUSED(sess_info->get_client_ip().to_string(buf, BUF_LEN));
737
gen_.next_column(buf);
740
if (sess_info->get_host_name().empty()) {
743
UNUSED(sess_info->get_host_name().to_string(buf, BUF_LEN));
744
gen_.next_column(buf);
747
uint64_t tx_id = sess_info->get_tx_id();
748
gen_.next_column(tx_id);
750
gen_.next_column(static_cast<uint64_t>(sess_info->get_thread_id()));
752
if (sess_info->get_ssl_cipher().empty()) {
755
UNUSED(sess_info->get_ssl_cipher().to_string(buf, BUF_LEN));
756
gen_.next_column(buf);
759
if (obmysql::COM_QUERY == sess_info->get_mysql_cmd() ||
760
obmysql::COM_STMT_EXECUTE == sess_info->get_mysql_cmd() ||
761
obmysql::COM_STMT_PREPARE == sess_info->get_mysql_cmd() ||
762
obmysql::COM_STMT_PREXECUTE == sess_info->get_mysql_cmd()) {
763
UNUSED(sess_info->get_current_trace_id().to_string(buf, BUF_LEN));
764
gen_.next_column(buf);
769
if (sess_info->is_in_transaction()) {
770
gen_.next_column(sess_info->get_tx_desc()->get_tx_state_str());
775
if (ObSQLSessionState::QUERY_ACTIVE == sess_info->get_session_state()) {
776
// time_sec = current time - sql packet received from easy time
777
int64_t time_sec = (::oceanbase::common::ObTimeUtility::current_time() - sess_info->get_query_start_time()) / 1000000;
778
gen_.next_column(time_sec);
780
int64_t time_sec = (::oceanbase::common::ObTimeUtility::current_time() - sess_info->get_cur_state_start_time()) / 1000000;
781
gen_.next_column(time_sec);
784
gen_.next_column(sess_info->get_retry_info().get_retry_cnt());
786
gen_.next_column(sess_info->get_retry_info().get_last_query_retry_err());
788
gen_.next_column(sess_info->get_action_name());
790
gen_.next_column(sess_info->get_module_name());
792
gen_.next_column(sess_info->get_client_info());
795
return !gen_.is_end();
798
LuaVtableGenerator& gen_;
801
int ret = OB_SUCCESS;
802
int argc = lua_gettop(L);
804
OB_LOG(ERROR, "call select_processlist() failed, bad arguments count, should be less than 2.");
807
std::vector<const char*> columns = {
835
LuaVtableGenerator gen(L, columns);
836
GetProcess iter(gen);
837
if (OB_FAIL(GCTX.session_mgr_->for_each_session(iter))) {
838
OB_LOG(ERROR, "failed to select_processlist", K(ret));
844
// list{list, list...} = select_sysstat()
845
int select_sysstat(lua_State* L)
847
int ret = OB_SUCCESS;
848
int argc = lua_gettop(L);
850
OB_LOG(ERROR, "call select_sysstat() failed, bad arguments count, should be less than 2.");
853
common::ObVector<uint64_t> ids;
854
std::vector<const char*> columns = {
864
GCTX.omt_->get_tenant_ids(ids);
865
LuaVtableGenerator gen(L, columns);
866
for (int64_t i = 0; i < ids.size() && !gen.is_end(); ++i) {
867
ObArenaAllocator diag_allocator;
868
HEAP_VAR(ObDiagnoseTenantInfo, diag_info, &diag_allocator) {
869
if (OB_FAIL(ObDIGlobalTenantCache::get_instance().get_the_diag_info(ids.at(i), diag_info))) {
870
OB_LOG(ERROR, "failed to get_the_diag_info", K(ids.at(i)), K(ret));
871
} else if (OB_FAIL(observer::ObAllVirtualSysStat::update_all_stats(ids.at(i), diag_info.get_set_stat_stats()))) {
872
OB_LOG(ERROR, "failed to update_all_stats", K(ids.at(i)), K(ret));
874
for (int64_t stat_idx = 0;
875
stat_idx < ObStatEventIds::STAT_EVENT_SET_END && !gen.is_end();
877
if (ObStatEventIds::STAT_EVENT_ADD_END == stat_idx) {
882
gen.next_column(ids.at(i));
885
if (stat_idx < ObStatEventIds::STAT_EVENT_ADD_END) {
886
gen.next_column(stat_idx);
888
gen.next_column(stat_idx - 1);
893
if (stat_idx < ObStatEventIds::STAT_EVENT_ADD_END) {
894
if (OB_ISNULL(diag_info.get_add_stat_stats().get(stat_idx))) {
896
OB_LOG(ERROR, "invalid argument", K(stat_idx), K(ids.at(i)));
898
gen.next_column(diag_info.get_add_stat_stats().get(stat_idx)->stat_value_);
901
if (OB_ISNULL(diag_info.get_set_stat_stats().get(stat_idx - ObStatEventIds::STAT_EVENT_ADD_END - 1))) {
903
OB_LOG(ERROR, "invalid argument", K(stat_idx), K(ids.at(i)));
905
gen.next_column(diag_info.get_set_stat_stats().get(stat_idx - ObStatEventIds::STAT_EVENT_ADD_END - 1)->stat_value_);
911
if (stat_idx < ObStatEventIds::STAT_EVENT_ADD_END) {
912
gen.next_column("ADD_VALUE");
914
gen.next_column("SET_VALUE");
918
gen.next_column(OB_STAT_EVENTS[stat_idx].stat_id_);
920
gen.next_column(OB_STAT_EVENTS[stat_idx].name_);
922
gen.next_column(OB_STAT_EVENTS[stat_idx].stat_class_);
924
gen.next_column(OB_STAT_EVENTS[stat_idx].can_visible_);
936
// list{list, list...} = select_memory_info()
937
int select_memory_info(lua_State *L)
939
int ret = OB_SUCCESS;
940
int argc = lua_gettop(L);
942
OB_LOG(ERROR, "call select_memory_info() failed, bad arguments count, should be less than 2.");
945
uint64_t *tenant_ids = nullptr;
946
std::vector<const char*> columns = {
955
LuaVtableGenerator gen(L, columns);
957
if (OB_NOT_NULL(tenant_ids = (uint64_t *)diagnose::alloc(OB_MAX_SERVER_TENANT_CNT * sizeof(uint64_t)))) {
958
get_tenant_ids(tenant_ids, OB_MAX_SERVER_TENANT_CNT, tenant_cnt);
960
for (int64_t i = 0; i < tenant_cnt && !gen.is_end(); ++i) {
961
auto tenant_id = tenant_ids[i];
962
for (int64_t ctx_id = 0; ctx_id < ObCtxIds::MAX_CTX_ID; ++ctx_id) {
963
auto ta = ObMallocAllocator::get_instance()->get_tenant_ctx_allocator(tenant_id, ctx_id);
965
ta = ObMallocAllocator::get_instance()->get_tenant_ctx_allocator_unrecycled(tenant_id,
971
IGNORE_RETURN ta->iter_label([&](lib::ObLabel &label, LabelItem *l_item)
973
const char *mod_name = label.str_;
974
int64_t hold = l_item->hold_;
975
int64_t used = l_item->used_;
976
int64_t count = l_item->count_;
980
gen.next_column(tenant_id);
982
gen.next_column(ctx_id);
984
gen.next_column(get_global_ctx_info().get_ctx_name(ctx_id));
986
gen.next_column(mod_name);
988
gen.next_column(hold);
990
gen.next_column(used);
992
gen.next_column(count);
1001
diagnose::free(tenant_ids);
1006
// list{list, list...} = select_tenant_ctx_memory_info()
1007
int select_tenant_ctx_memory_info(lua_State *L)
1009
int argc = lua_gettop(L);
1011
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call select_tenant_ctx_memory_info() failed, bad arguments count, should be less than 2.");
1014
uint64_t *tenant_ids = nullptr;
1016
std::vector<const char*> columns = {
1024
LuaVtableGenerator gen(L, columns);
1025
if (OB_NOT_NULL(tenant_ids = (uint64_t *)diagnose::alloc(OB_MAX_SERVER_TENANT_CNT * sizeof(uint64_t)))) {
1026
get_tenant_ids(tenant_ids, OB_MAX_SERVER_TENANT_CNT, tenant_cnt);
1029
for (int64_t i = 0; i < tenant_cnt && !gen.is_end(); ++i) {
1030
auto tenant_id = tenant_ids[i];
1031
for (int64_t ctx_id = 0; ctx_id < ObCtxIds::MAX_CTX_ID; ++ctx_id) {
1032
auto ta = ObMallocAllocator::get_instance()->get_tenant_ctx_allocator(tenant_id, ctx_id);
1033
if (nullptr == ta) {
1034
ta = ObMallocAllocator::get_instance()->get_tenant_ctx_allocator_unrecycled(tenant_id,
1037
if (nullptr == ta) {
1043
gen.next_column(tenant_id);
1045
gen.next_column(ctx_id);
1047
gen.next_column(get_global_ctx_info().get_ctx_name(ctx_id));
1049
gen.next_column(ta->get_hold());
1051
gen.next_column(ta->get_used());
1053
gen.next_column(ta->get_limit());
1060
diagnose::free(tenant_ids);
1065
// list{list, list...} = select_trans_stat()
1066
int select_trans_stat(lua_State *L)
1068
int ret = OB_SUCCESS;
1069
int argc = lua_gettop(L);
1070
ObTransService *trans_service = nullptr;
1071
ObArray<uint64_t> tenant_ids;
1074
OB_LOG(ERROR, "call select_trans_stat() failed, bad arguments count, should be 0.");
1076
} else if (OB_ISNULL(GCTX.omt_)) {
1077
OB_LOG(ERROR, "omt is nullptr");
1079
} else if (OB_FAIL(GCTX.omt_->get_mtl_tenant_ids(tenant_ids))) {
1080
OB_LOG(ERROR, "failed to get tenant_ids", K(ret));
1083
HEAP_VAR(ObTxStatIterator, iter) {
1085
for (int i = 0; i < tenant_ids.count() && OB_SUCC(ret); ++i) {
1086
uint64_t tenant_id = tenant_ids.at(i);
1087
MTL_SWITCH(tenant_id) {
1088
auto* txs = MTL(transaction::ObTransService*);
1089
if (OB_FAIL(txs->iterate_all_observer_tx_stat(iter))) {
1090
OB_LOG(ERROR, "iterate transaction stat failed", K(ret));
1096
} else if (OB_FAIL(iter.set_ready())) {
1097
OB_LOG(ERROR, "ObTxStatIterator set ready error", K(ret));
1100
ret = iter.get_next(tx_stat);
1102
static constexpr int64_t OB_MAX_BUFFER_SIZE = 512;
1103
static constexpr int64_t OB_MIN_BUFFER_SIZE = 128;
1104
std::vector<const char*> columns = {
1113
"tx_ctx_create_time",
1132
LuaVtableGenerator gen(L, columns);
1133
while (OB_SUCC(ret) && !gen.is_end()) {
1136
gen.next_column(tx_stat.tenant_id_);
1138
gen.next_column(tx_stat.tx_type_);
1140
gen.next_column(tx_stat.tx_id_.get_id());
1142
gen.next_column(tx_stat.session_id_);
1144
char addr_buf[MAX_IP_PORT_LENGTH + 8];
1145
tx_stat.scheduler_addr_.to_string(addr_buf, MAX_IP_PORT_LENGTH + 8);
1146
gen.next_column(addr_buf);
1148
gen.next_column(tx_stat.has_decided_);
1150
gen.next_column(tx_stat.ls_id_.id());
1152
if (0 < tx_stat.participants_.count()) {
1153
char participants_buffer[OB_MAX_BUFFER_SIZE];
1154
tx_stat.participants_.to_string(participants_buffer, OB_MAX_BUFFER_SIZE);
1155
gen.next_column(participants_buffer);
1157
ret = iter.get_next(tx_stat);
1159
// tx_ctx_create_time
1160
gen.next_column(tx_stat.tx_ctx_create_time_);
1162
gen.next_column(tx_stat.tx_expired_time_);
1164
gen.next_column(tx_stat.ref_cnt_);
1166
gen.next_column(tx_stat.last_op_sn_);
1168
gen.next_column(tx_stat.pending_write_);
1170
gen.next_column(tx_stat.state_);
1172
gen.next_column(tx_stat.part_tx_action_);
1174
gen.next_column((uint64_t)tx_stat.tx_ctx_addr_);
1176
gen.next_column(-1);
1178
gen.next_column(tx_stat.pending_log_size_);
1180
gen.next_column(tx_stat.flushed_log_size_);
1182
gen.next_column(tx_stat.role_state_);
1184
gen.next_column(tx_stat.is_exiting_);
1186
gen.next_column(tx_stat.coord_.id());
1188
gen.next_column(tx_stat.last_request_ts_);
1190
gen.next_column(tx_stat.xid_.get_gtrid_str());
1192
gen.next_column(tx_stat.xid_.get_bqual_str());
1194
gen.next_column(tx_stat.xid_.get_format_id());
1197
ret = iter.get_next(tx_stat);
1200
if (OB_FAIL(ret) && OB_ITER_END != ret) {
1201
OB_LOG(ERROR, "iter failed", K(ret));
1207
// list{list, list...} = select_sql_workarea_active()
1208
int select_sql_workarea_active(lua_State *L)
1210
int ret = OB_SUCCESS;
1211
int argc = lua_gettop(L);
1213
OB_LOG(ERROR, "call select_sql_workarea_active() failed, bad arguments count, should be less than 2.");
1215
} else if (OB_ISNULL(GCTX.omt_)) {
1216
OB_LOG(ERROR, "GCTX.omt_ is NULL");
1219
ObArray<uint64_t> ids;
1220
common::ObSEArray<sql::ObSqlWorkareaProfileInfo, 32> wa_actives;
1221
std::vector<const char*> columns = {
1238
LuaVtableGenerator gen(L, columns);
1239
GCTX.omt_->get_mtl_tenant_ids(ids);
1240
for (int64_t i = 0; i < ids.size() && !gen.is_end(); ++i) {
1241
uint64_t tenant_id = ids[i];
1243
MTL_SWITCH(tenant_id) {
1244
auto *sql_mem_mgr = MTL(ObTenantSqlMemoryManager*);
1245
if (OB_NOT_NULL(sql_mem_mgr) && OB_FAIL(sql_mem_mgr->get_all_active_workarea(wa_actives))) {
1246
OB_LOG(ERROR, "failed to get workarea stat", K(ret));
1249
for (int64_t j = 0; j < wa_actives.count() && !gen.is_end(); ++j) {
1250
auto &wa_active = wa_actives[j];
1253
gen.next_column(wa_active.plan_id_);
1255
gen.next_column(wa_active.sql_id_);
1257
gen.next_column(wa_active.sql_exec_id_);
1259
gen.next_column(get_phy_op_name(wa_active.profile_.get_operator_type()));
1261
gen.next_column(wa_active.profile_.get_operator_id());
1263
gen.next_column(wa_active.session_id_);
1265
gen.next_column(ObTimeUtility::current_time() - wa_active.profile_.get_active_time());
1267
gen.next_column(wa_active.profile_.get_cache_size());
1269
gen.next_column(wa_active.profile_.get_expect_size());
1271
gen.next_column(wa_active.profile_.get_mem_used());
1273
gen.next_column(wa_active.profile_.get_max_mem_used());
1275
gen.next_column(wa_active.profile_.get_number_pass());
1277
gen.next_column(wa_active.profile_.get_dumped_size());
1279
gen.next_column(tenant_id);
1281
if (wa_active.profile_.get_auto_policy()) {
1282
gen.next_column(EXECUTION_AUTO_POLICY);
1284
gen.next_column(EXECUTION_MANUAL_POLICY);
1294
// list{list, list...} = select_sys_task_status()
1295
int select_sys_task_status(lua_State *L)
1297
int ret = OB_SUCCESS;
1298
int argc = lua_gettop(L);
1299
HEAP_VAR(share::ObSysStatMgrIter, iter) {
1301
OB_LOG(ERROR, "call select_sys_task_status() failed, bad arguments count, should be less than 2.");
1303
} else if (OB_FAIL(SYS_TASK_STATUS_MGR.get_iter(iter))) {
1304
OB_LOG(ERROR, "failed to get iter", K(ret));
1306
} else if (!iter.is_ready()) {
1307
OB_LOG(ERROR, "iter not ready");
1309
share::ObSysTaskStat status;
1310
std::vector<const char*> columns = {
1318
LuaVtableGenerator gen(L, columns);
1319
while (OB_SUCC(iter.get_next(status)) && !gen.is_end()) {
1322
gen.next_column(status.start_time_);
1324
gen.next_column(sys_task_type_to_str(status.task_type_));
1327
char task_id[common::OB_TRACE_STAT_BUFFER_SIZE];
1328
int64_t n = status.task_id_.to_string(task_id, sizeof(task_id));
1329
if (n < 0 || n >= sizeof(task_id)) {
1330
OB_LOG(ERROR, "buffer not enough");
1333
gen.next_column(task_id);
1337
gen.next_column(status.tenant_id_);
1339
gen.next_column(status.comment_);
1341
gen.next_column(status.is_cancel_);
1350
// list{list, list...} = select_dump_tenant_info()
1351
int select_dump_tenant_info(lua_State *L)
1353
int ret = OB_SUCCESS;
1354
int argc = lua_gettop(L);
1355
auto *omt = GCTX.omt_;
1357
OB_LOG(ERROR, "call select_dump_tenant_info() failed, bad arguments count, should be less than 2.");
1359
} else if (OB_ISNULL(omt)) {
1360
OB_LOG(ERROR, "omt is nullptr");
1363
auto *omt = GCTX.omt_;
1364
std::vector<const char*> columns = {
1382
"recv_large_req_cnt",
1383
"recv_large_queries",
1386
"lq_warting_workers",
1387
"req_queue_total_size",
1396
LuaVtableGenerator gen(L, columns);
1397
auto func = [&] (omt::ObTenant &t) {
1400
gen.next_column(t.id_);
1402
gen.next_column(static_cast<int64_t>(t.get_compat_mode()));
1404
gen.next_column(t.unit_min_cpu_);
1406
gen.next_column(t.unit_max_cpu_);
1412
gen.next_column(t.worker_count());
1414
gen.next_column(t.worker_count());
1420
gen.next_column(t.stopped_);
1424
gen.next_column(t.recv_hp_rpc_cnt_);
1426
gen.next_column(t.recv_np_rpc_cnt_);
1428
gen.next_column(t.recv_lp_rpc_cnt_);
1430
gen.next_column(t.recv_mysql_cnt_);
1432
gen.next_column(t.recv_task_cnt_);
1433
// recv_large_req_cnt
1434
gen.next_column(t.recv_large_req_cnt_);
1435
// recv_large_queries
1436
gen.next_column(t.tt_large_quries_);
1438
gen.next_column(t.workers_.get_size());
1440
gen.next_column(t.workers_.get_size());
1441
// lq_warting_workers
1443
// req_queue_total_size
1444
gen.next_column(t.req_queue_.size());
1446
gen.next_column(t.req_queue_.queue_size(0));
1448
gen.next_column(t.req_queue_.queue_size(1));
1450
gen.next_column(t.req_queue_.queue_size(2));
1452
gen.next_column(t.req_queue_.queue_size(3));
1454
gen.next_column(t.req_queue_.queue_size(4));
1456
gen.next_column(t.req_queue_.queue_size(5));
1458
gen.next_column(t.lq_retry_queue_size());
1462
if (OB_FAIL(omt->for_each(func))) {
1463
OB_LOG(ERROR, "omt for each failed", K(ret));
1469
// list{list, list...} = select_disk_stat()
1470
int select_disk_stat(lua_State *L)
1472
int ret = OB_SUCCESS;
1473
int argc = lua_gettop(L);
1474
ObDeviceHealthStatus dhs = DEVICE_HEALTH_NORMAL;
1475
int64_t data_disk_abnormal_time = 0;
1477
OB_LOG(ERROR, "call select_disk_stat() failed, bad arguments count, should be less than 2.");
1479
} else if (OB_FAIL(ObIOManager::get_instance().get_device_health_status(dhs,
1480
data_disk_abnormal_time))) {
1481
OB_LOG(WARN, "get device health status failed", K(ret));
1484
std::vector<const char*> columns = {
1489
"disk_error_begin_ts"
1491
LuaVtableGenerator gen(L, columns);
1495
gen.next_column(OB_SERVER_BLOCK_MGR.get_total_macro_block_count() * OB_SERVER_BLOCK_MGR.get_macro_block_size());
1497
gen.next_column(OB_SERVER_BLOCK_MGR.get_used_macro_block_count() * OB_SERVER_BLOCK_MGR.get_macro_block_size());
1499
gen.next_column(OB_SERVER_BLOCK_MGR.get_free_macro_block_count() * OB_SERVER_BLOCK_MGR.get_macro_block_size());
1501
gen.next_column(DEVICE_HEALTH_NORMAL != dhs ? 0 : 1);
1502
// disk_error_begin_ts
1503
gen.next_column(DEVICE_HEALTH_NORMAL != dhs ? data_disk_abnormal_time : 0);
1510
// list{list, list...} = select_tenant_memory_info()
1511
int select_tenant_memory_info(lua_State *L)
1513
int argc = lua_gettop(L);
1515
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call select_tenant_memory_info() failed, bad arguments count, should be less than 2.");
1518
uint64_t *tenant_ids = nullptr;
1520
std::vector<const char*> columns = {
1525
LuaVtableGenerator gen(L, columns);
1526
if (OB_NOT_NULL(tenant_ids = (uint64_t *)diagnose::alloc(OB_MAX_SERVER_TENANT_CNT * sizeof(uint64_t)))) {
1527
get_tenant_ids(tenant_ids, OB_MAX_SERVER_TENANT_CNT, tenant_cnt);
1529
for (int64_t i = 0; i < tenant_cnt && !gen.is_end(); ++i) {
1530
auto tenant_id = tenant_ids[i];
1533
gen.next_column(tenant_id);
1535
gen.next_column(ObMallocAllocator::get_instance()->get_tenant_hold(tenant_id));
1537
gen.next_column(ObMallocAllocator::get_instance()->get_tenant_limit(tenant_id));
1541
diagnose::free(tenant_ids);
1546
// list{list, list...} = select_mem_leak_checker_info()
1547
int select_mem_leak_checker_info(lua_State *L)
1549
int argc = lua_gettop(L);
1550
ObMemLeakChecker* leak_checker = &get_mem_leak_checker();
1552
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_mem_leak_checker_info() failed, bad arguments count, should be less than 2.");
1554
} else if (OB_ISNULL(leak_checker)) {
1555
OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "leak checker is null");
1558
int ret = OB_SUCCESS;
1559
ObMemLeakChecker::mod_info_map_t info_map;
1560
if (OB_FAIL(info_map.create(10000))) {
1561
OB_LOG(ERROR, "failed to create hashmap", K(ret));
1562
} else if (OB_FAIL(leak_checker->load_leak_info_map(info_map))) {
1563
OB_LOG(ERROR, "failed to collection leak info", K(ret));
1565
std::vector<const char*> columns = {
1572
LuaVtableGenerator gen(L, columns);
1573
for (auto it = info_map->begin(); it != info_map->end() && !gen.is_end(); ++it) {
1576
gen.next_column(leak_checker->get_str());
1578
gen.next_column("user");
1580
gen.next_column(it->second.first);
1582
gen.next_column(it->second.second);
1584
gen.next_column(it->first.bt_);
1593
// list{list, list...} = select_compaction_diagnose_info()
1594
int select_compaction_diagnose_info(lua_State *L)
1596
int argc = lua_gettop(L);
1598
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_compaction_diagnose_info() failed, bad arguments count, should be less than 2.");
1601
int ret = OB_SUCCESS;
1602
compaction::ObCompactionDiagnoseIterator diagnose_info_iter;
1603
// OB_SYS_TENANT_ID means dump all
1604
if (OB_FAIL(diagnose_info_iter.open(OB_SYS_TENANT_ID))) {
1605
OB_LOG(ERROR, "Fail to open suggestion iter", K(ret));
1608
std::vector<const char*> columns = {
1617
LuaVtableGenerator gen(L, columns);
1618
compaction::ObCompactionDiagnoseInfo diagnose_info;
1619
while (OB_SUCC(diagnose_info_iter.get_next_info(diagnose_info)) && !gen.is_end()) {
1622
gen.next_column(diagnose_info.tenant_id_);
1624
gen.next_column(merge_type_to_str(diagnose_info.merge_type_));
1626
gen.next_column(diagnose_info.ls_id_);
1628
gen.next_column(diagnose_info.tablet_id_);
1630
gen.next_column(diagnose_info.get_diagnose_status_str(diagnose_info.status_));
1632
gen.next_column(diagnose_info.timestamp_);
1634
gen.next_column(diagnose_info.diagnose_info_);
1638
if (OB_FAIL(ret) && OB_ITER_END != ret) {
1639
OB_LOG(ERROR, "Fail to get next suggestion info", K(ret));
1646
// list{list, list...} = select_server_schema_info()
1647
int select_server_schema_info(lua_State *L)
1649
int argc = lua_gettop(L);
1651
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_server_schema_info() failed, bad arguments count, should be less than 2.");
1654
int ret = OB_SUCCESS;
1655
const static int64_t DEFAULT_TENANT_NUM = 10;
1656
ObSEArray<uint64_t, DEFAULT_TENANT_NUM> tenant_ids;
1657
share::schema::ObSchemaGetterGuard guard;
1658
auto& schema_service = OBSERVER.get_root_service().get_schema_service();
1659
if (OB_FAIL(schema_service.get_tenant_schema_guard(OB_SYS_TENANT_ID, guard))) {
1660
OB_LOG(ERROR, "fail to get schema guard", K(ret));
1662
} else if (OB_FAIL(guard.get_tenant_ids(tenant_ids))) {
1663
OB_LOG(ERROR, "fail to get tenant_ids", K(ret));
1666
std::vector<const char*> columns = {
1668
"refreshed_schema_version",
1669
"received_schema_version",
1672
"min_sstable_schema_version"
1674
LuaVtableGenerator gen(L, columns);
1675
for (uint64_t idx = 0; idx < tenant_ids.count() && !gen.is_end(); ++idx) {
1676
const uint64_t tenant_id = tenant_ids[idx];
1677
int64_t refreshed_schema_version = OB_INVALID_VERSION;
1678
int64_t received_schema_version = OB_INVALID_VERSION;
1679
int64_t schema_count = OB_INVALID_ID;
1680
int64_t schema_size = OB_INVALID_ID;
1681
if (OB_FAIL(schema_service.get_tenant_refreshed_schema_version(tenant_id, refreshed_schema_version))) {
1682
OB_LOG(ERROR, "fail to get tenant refreshed schema version", K(ret), K(tenant_id), K(refreshed_schema_version));
1683
} else if (OB_FAIL(schema_service.get_tenant_received_broadcast_version(tenant_id, received_schema_version))) {
1684
OB_LOG(ERROR, "fail to get tenant receieved schema version", K(ret), K(tenant_id), K(received_schema_version));
1686
int tmp_ret = OB_SUCCESS;
1687
if (OB_SUCCESS != (tmp_ret = schema_service.get_tenant_schema_guard(tenant_id, guard))) {
1688
OB_LOG(ERROR, "fail to get schema guard", K(tmp_ret), K(tenant_id));
1689
} else if (OB_SUCCESS != (tmp_ret = guard.get_schema_count(tenant_id, schema_count))) {
1690
OB_LOG(ERROR, "fail to get schema count", K(tmp_ret), K(tenant_id));
1691
} else if (OB_SUCCESS != (tmp_ret = guard.get_schema_size(tenant_id, schema_size))) {
1692
OB_LOG(ERROR, "fail to get schema size", K(tmp_ret), K(tenant_id));
1696
gen.next_column(tenant_id);
1697
// refreshed_schema_version
1698
gen.next_column(refreshed_schema_version);
1699
// received_schema_version
1700
gen.next_column(received_schema_version);
1702
gen.next_column(schema_count);
1704
gen.next_column(schema_size);
1705
// min_sstable_schema_version
1706
gen.next_column(OB_INVALID_VERSION);
1716
// list{list, list...} = select_schema_slot()
1717
int select_schema_slot(lua_State *L)
1719
int argc = lua_gettop(L);
1721
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_schema_slot() failed, bad arguments count, should be less than 2.");
1724
int ret = OB_SUCCESS;
1725
auto& schema_service = OBSERVER.get_root_service().get_schema_service();
1726
const static int64_t DEFAULT_TENANT_NUM = 10;
1727
ObSEArray<uint64_t, DEFAULT_TENANT_NUM> tenant_ids;
1728
if (OB_FAIL(schema_service.get_schema_store_tenants(tenant_ids))) {
1729
OB_LOG(ERROR, "fail to get schema store tenants", K(ret));
1732
std::vector<const char*> columns = {
1740
LuaVtableGenerator gen(L, columns);
1741
for (int64_t idx = 0; idx < tenant_ids.count() && !gen.is_end(); ++idx) {
1742
const static int64_t DEFAULT_SLOT_NUM = 32;
1743
ObSEArray<ObSchemaSlot, DEFAULT_SLOT_NUM> schema_slot_infos;
1744
uint64_t tenant_id = tenant_ids[idx];
1745
if (OB_FAIL(schema_service.get_tenant_slot_info(get_global_allocator(), tenant_id, schema_slot_infos))) {
1746
OB_LOG(ERROR, "fail to get tenant slot info", K(ret), K(tenant_id));
1748
for (int64_t slot_idx = 0; slot_idx < schema_slot_infos.count() && !gen.is_end(); ++slot_idx) {
1749
auto& schema_slot = schema_slot_infos.at(slot_idx);
1752
gen.next_column(schema_slot.get_tenant_id());
1754
gen.next_column(schema_slot.get_slot_id());
1756
gen.next_column(schema_slot.get_schema_version());
1758
gen.next_column(schema_slot.get_schema_count());
1760
gen.next_column(schema_slot.get_ref_cnt());
1762
if (OB_NOT_NULL(schema_slot.get_mod_ref_infos().ptr())) {
1763
gen.next_column(schema_slot.get_mod_ref_infos());
1765
gen.next_column("");
1771
for (int64_t slot_idx = 0; slot_idx < schema_slot_infos.count(); ++slot_idx) {
1772
auto* ptr = schema_slot_infos.at(slot_idx).get_mod_ref_infos().ptr();
1773
if (OB_NOT_NULL(ptr)) {
1774
get_global_allocator().free((void*)ptr);
1776
schema_slot_infos.at(slot_idx).reset();
1778
schema_slot_infos.reset();
1785
#define GET_OTHER_TSI_ADDR(var_name, addr) \
1786
const int64_t var_name##_offset = ((int64_t)addr - (int64_t)pthread_self()); \
1787
decltype(*addr) var_name = *(decltype(addr))(thread_base + var_name##_offset);
1789
// list{list, list...} = dump_threads_info()
1790
int dump_thread_info(lua_State *L)
1792
int argc = lua_gettop(L);
1794
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call dump_thread_info() failed, bad arguments count, should be less than 2.");
1796
std::vector<const char*> columns = {
1807
LuaVtableGenerator gen(L, columns);
1808
pid_t pid = getpid();
1809
StackMgr::Guard guard(g_stack_mgr);
1810
for(auto* header = *guard; OB_NOT_NULL(header) && !gen.is_end(); header = guard.next()) {
1811
auto* thread_base = (char*)(header->pth_);
1812
if (OB_NOT_NULL(thread_base)) {
1813
// avoid SMART_CALL stack
1816
GET_OTHER_TSI_ADDR(tname, &(ob_get_tname()[0]));
1817
// PAY ATTENTION HERE
1818
gen.next_column(thread_base + tname_offset);
1820
GET_OTHER_TSI_ADDR(tid, &get_tid_cache());
1821
gen.next_column(tid);
1825
snprintf(addr, 32, "%p", thread_base);
1826
gen.next_column(addr);
1829
GET_OTHER_TSI_ADDR(loop_ts, &oceanbase::lib::Thread::loop_ts_);
1830
gen.next_column(loop_ts);
1834
GET_OTHER_TSI_ADDR(locks_addr, &(ObLatch::current_locks[0]));
1835
GET_OTHER_TSI_ADDR(slot_cnt, &ObLatch::max_lock_slot_idx)
1836
const int64_t cnt = std::min(ARRAYSIZEOF(ObLatch::current_locks), (int64_t)slot_cnt);
1837
decltype(&locks_addr) locks = (decltype(&locks_addr))(thread_base + locks_addr_offset);
1839
for (int64_t i = 0, j = 0; i < cnt; ++i) {
1840
int64_t idx = (slot_cnt + i) % ARRAYSIZEOF(ObLatch::current_locks);
1841
if (OB_NOT_NULL(locks[idx]) && j < 256) {
1842
bool has_segv = false;
1844
struct iovec local_iov = {&val, sizeof(val)};
1845
struct iovec remote_iov = {locks[idx], sizeof(val)};
1846
ssize_t n = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
1847
if (n != sizeof(val)) {
1848
} else if (0 != val) {
1849
j += snprintf(addrs + j, 256 - j, "%p ", locks[idx]);
1853
if (0 == addrs[0]) {
1854
gen.next_column("NULL");
1856
gen.next_column(addrs);
1860
GET_OTHER_TSI_ADDR(wait_addr, &ObLatch::current_wait);
1861
if (OB_NOT_NULL(wait_addr)) {
1863
snprintf(addr, 32, "%p", wait_addr);
1864
gen.next_column(addr);
1866
gen.next_column("NULL");
1870
GET_OTHER_TSI_ADDR(trace_id, ObCurTraceId::get_trace_id());
1871
char trace_id_buf[40];
1872
IGNORE_RETURN trace_id.to_string(trace_id_buf, 40);
1873
gen.next_column(trace_id_buf);
1876
GET_OTHER_TSI_ADDR(blocking_ts, &Thread::blocking_ts_);
1878
GET_OTHER_TSI_ADDR(join_addr, &Thread::thread_joined_);
1879
GET_OTHER_TSI_ADDR(sleep_us, &Thread::sleep_us_);
1880
const char* status_str = nullptr;
1881
if (0 != join_addr) {
1882
status_str = "Join";
1883
} else if (0 != sleep_us) {
1884
status_str = "Sleep";
1885
} else if (0 != blocking_ts) {
1886
status_str = "Wait";
1890
gen.next_column(status_str);
1894
GET_OTHER_TSI_ADDR(wait_addr, &ObLatch::current_wait);
1895
GET_OTHER_TSI_ADDR(join_addr, &Thread::thread_joined_);
1896
GET_OTHER_TSI_ADDR(sleep_us, &Thread::sleep_us_);
1897
GET_OTHER_TSI_ADDR(rpc_dest_addr, &Thread::rpc_dest_addr_);
1898
GET_OTHER_TSI_ADDR(event, &Thread::wait_event_);
1899
constexpr int64_t BUF_LEN = 64;
1900
char wait_event[BUF_LEN];
1902
struct iovec local_iov = {&addr, sizeof(ObAddr)};
1903
struct iovec remote_iov = {thread_base + rpc_dest_addr_offset, sizeof(ObAddr)};
1904
wait_event[0] = '\0';
1905
if (0 != join_addr) {
1906
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "thread %u %ld", *(uint32_t*)(join_addr + tid_offset), tid_offset);
1907
} else if (OB_NOT_NULL(wait_addr)) {
1909
struct iovec local_iov = {&val, sizeof(val)};
1910
struct iovec remote_iov = {wait_addr, sizeof(val)};
1911
ssize_t n = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
1912
if (n != sizeof(val)) {
1913
} else if (0 != (val & (1<<30))) {
1914
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "wrlock on %u", val & 0x3fffffff);
1916
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "%u rdlocks", val & 0x3fffffff);
1918
} else if (sizeof(ObAddr) == process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0)
1919
&& addr.is_valid()) {
1920
GET_OTHER_TSI_ADDR(pcode, &Thread::pcode_);
1923
if (((pos1 = snprintf(wait_event, 37, "rpc 0x%X(%s", pcode, obrpc::ObRpcPacketSet::instance().name_of_idx(obrpc::ObRpcPacketSet::instance().idx_of_pcode(pcode)) + 3)) > 0)
1924
&& ((pos2 = snprintf(wait_event + std::min(36L, pos1), 6, ") to ")) > 0)) {
1925
int64_t pos = std::min(36L, pos1) + std::min(5L, pos2);
1926
pos += addr.to_string(wait_event + pos, BUF_LEN - pos);
1928
} else if (0 != blocking_ts && (0 != (Thread::WAIT_IN_TENANT_QUEUE & event))) {
1929
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "tenant worker request");
1930
} else if (0 != blocking_ts && (0 != (Thread::WAIT_FOR_IO_EVENT & event))) {
1931
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "IO events");
1932
} else if (0 != blocking_ts && (0 != (Thread::WAIT_FOR_LOCAL_RETRY & event))) {
1933
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "local retry");
1934
} else if (0 != blocking_ts && (0 != (Thread::WAIT_FOR_PX_MSG & event))) {
1935
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "px message");
1936
} else if (0 != sleep_us) {
1937
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "%ld us", sleep_us);
1938
} else if (0 != blocking_ts) {
1939
IGNORE_RETURN snprintf(wait_event, BUF_LEN, "%ld us", common::ObTimeUtility::fast_current_time() - blocking_ts);
1941
gen.next_column(wait_event);
1950
// list{list, list...} = select_malloc_sample_info()
1951
int select_malloc_sample_info(lua_State *L)
1953
int ret = OB_SUCCESS;
1954
int argc = lua_gettop(L);
1955
ObMallocSampleMap malloc_sample_map;
1957
OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_malloc_sample_info() failed, bad arguments count, should be less than 2.");
1959
} else if (OB_FAIL(malloc_sample_map.create(1000, "MallocInfoMap", "MallocInfoMap"))) {
1960
OB_LOG(ERROR, "failed to create hashmap", K(ret));
1961
} else if (OB_FAIL(ObMemoryDump::get_instance().load_malloc_sample_map(malloc_sample_map))) {
1962
OB_LOG(ERROR, "failed to create memory info map", K(ret));
1964
std::vector<const char*> columns = {
1973
LuaVtableGenerator gen(L, columns);
1974
for (auto it = malloc_sample_map.begin(); it != malloc_sample_map.end() && !gen.is_end(); ++it) {
1977
gen.next_column(it->first.tenant_id_);
1979
gen.next_column(it->first.ctx_id_);
1981
gen.next_column(it->first.label_);
1984
char bt[MAX_BACKTRACE_LENGTH];
1985
IGNORE_RETURN parray(bt, sizeof(bt), (int64_t*)it->first.bt_, AOBJECT_BACKTRACE_COUNT);
1986
gen.next_column(bt);
1989
gen.next_column(get_global_ctx_info().get_ctx_name(it->first.ctx_id_));
1991
gen.next_column(it->second.alloc_count_);
1993
gen.next_column(it->second.alloc_bytes_);
2001
// int = set_system_tenant_limit_mode(int)
2002
int set_system_tenant_limit_mode(lua_State* L)
2004
int ret = OB_SUCCESS;
2005
int argc = lua_gettop(L);
2007
OB_LOG(ERROR, "call set_system_tenant_limit_mode() failed, bad arguments count, should be 1.");
2008
ret = OB_INVALID_ARGUMENT;
2010
luaL_checktype(L, 1, LUA_TNUMBER);
2011
const int64_t limit_mode = lua_tointeger(L, 1);
2012
#ifdef ENABLE_500_MEMORY_LIMIT
2013
GMEMCONF.set_500_tenant_limit(limit_mode);
2015
lua_pushinteger(L, 1);
2018
lua_pushinteger(L, -1);
2025
int get_tenant_sysstat(int64_t tenant_id, int64_t statistic, int64_t &value)
2027
int ret = OB_SUCCESS;
2028
ObArenaAllocator diag_allocator;
2029
HEAP_VAR(ObDiagnoseTenantInfo, diag_info, &diag_allocator) {
2031
|| statistic >= ObStatEventIds::STAT_EVENT_SET_END
2032
|| ObStatEventIds::STAT_EVENT_ADD_END == statistic) {
2033
ret = OB_INVALID_ARGUMENT;
2034
} else if (OB_FAIL(ObDIGlobalTenantCache::get_instance().get_the_diag_info(tenant_id, diag_info))) {
2036
} else if (OB_FAIL(observer::ObAllVirtualSysStat::update_all_stats(tenant_id, diag_info.get_set_stat_stats()))) {
2038
} else if (statistic < ObStatEventIds::STAT_EVENT_ADD_END) {
2039
ObStatEventAddStat* stat = diag_info.get_add_stat_stats().get(statistic);
2040
if (OB_ISNULL(stat)) {
2041
ret = OB_INVALID_ARGUMENT;
2043
value = stat->stat_value_;
2046
ObStatEventSetStat* stat = diag_info.get_set_stat_stats().get(statistic - ObStatEventIds::STAT_EVENT_ADD_END - 1);
2047
if (OB_ISNULL(stat)) {
2048
ret = OB_INVALID_ARGUMENT;
2050
value = stat->stat_value_;
2057
int summary_each_eio_info(char *buf, int &pos, int buf_len, easy_io_t *eio, const char *rpc_des)
2059
int ret = OB_SUCCESS;
2060
int io_th_count = 0;
2061
easy_io_thread_t *ioth = NULL;
2062
easy_connection_t *c = NULL;
2066
if (OB_ISNULL(buf) || OB_ISNULL(eio) || OB_ISNULL(rpc_des)) {
2068
} else if (pos >= buf_len) {
2069
ret = OB_INVALID_ARGUMENT;
2071
len = strlen(rpc_des);
2072
if (pos + len > buf_len) {
2073
ret = OB_INVALID_ARGUMENT;
2075
strncpy(buf + pos, rpc_des, len);
2077
io_th_count = eio->io_thread_count;
2079
for (int i = 0; i < io_th_count && (!ret); i++) {
2080
ioth = (easy_io_thread_t *)easy_thread_pool_index(eio->io_thread_pool, i);
2081
snprintf(output, sizeof(output), " ioth%d, rx_doing_request_count:%d, rx_done_request_count:%lu, "
2082
"tx_doing_request_count:%d, tx_done_request_count:%lu\n",
2083
i,ioth->rx_doing_request_count, ioth->rx_done_request_count,
2084
ioth->tx_doing_request_count, ioth->tx_done_request_count);
2085
len = strlen(output);
2086
if (pos + len > buf_len) {
2087
ret = OB_INVALID_ARGUMENT;
2089
strncpy(buf + pos, output, len);
2091
easy_list_for_each_entry(c, &ioth->connected_list, conn_list_node) {
2092
snprintf(output, sizeof(output), " connection:%s, doing:%d, done:%lu\n", easy_connection_str(c),
2093
c->con_summary->doing_request_count, c->con_summary->done_request_count);
2094
len = strlen(output);
2095
if (len + pos > buf_len) {
2096
ret = OB_INVALID_ARGUMENT;
2099
strncpy(buf + pos, output, len);
2110
void *diagnose::alloc(const int size)
2112
return get_global_allocator().alloc(size);
2115
void diagnose::free(void *ptr)
2117
if (OB_NOT_NULL(ptr)) {
2118
get_global_allocator().free(ptr);
2122
void APIRegister::register_api(lua_State* L)
2124
lua_register(L, "usage", usage);
2125
lua_register(L, "print_to_client", print_to_client);
2126
lua_register(L, "now", now);
2127
lua_register(L, "get_tenant_id_list", get_tenant_id_list);
2128
lua_register(L, "get_tenant_mem_limit", get_tenant_mem_limit);
2129
lua_register(L, "get_tenant_sysstat_by_id", get_tenant_sysstat_by_id);
2130
lua_register(L, "get_tenant_sysstat_by_name", get_tenant_sysstat_by_name);
2131
lua_register(L, "get_easy_diagnose_info", get_easy_diagnose_info);
2132
lua_register(L, "get_tenant_pcode_statistics", get_tenant_pcode_statistics);
2133
lua_register(L, "select_processlist", select_processlist);
2134
lua_register(L, "select_sysstat", select_sysstat);
2135
lua_register(L, "select_memory_info", select_memory_info);
2136
lua_register(L, "select_tenant_ctx_memory_info", select_tenant_ctx_memory_info);
2137
lua_register(L, "select_trans_stat", select_trans_stat);
2138
lua_register(L, "select_sql_workarea_active", select_sql_workarea_active);
2139
lua_register(L, "select_sys_task_status", select_sys_task_status);
2140
lua_register(L, "select_dump_tenant_info", select_dump_tenant_info);
2141
lua_register(L, "select_disk_stat", select_disk_stat);
2142
lua_register(L, "select_tenant_memory_info", select_tenant_memory_info);
2143
lua_register(L, "set_log_probe", set_log_probe);
2144
lua_register(L, "show_log_probe", show_log_probe);
2145
lua_register(L, "select_mem_leak_checker_info", select_mem_leak_checker_info);
2146
lua_register(L, "select_compaction_diagnose_info", select_compaction_diagnose_info);
2147
lua_register(L, "select_server_schema_info", select_server_schema_info);
2148
lua_register(L, "select_schema_slot", select_schema_slot);
2149
lua_register(L, "dump_thread_info", dump_thread_info);
2150
lua_register(L, "select_malloc_sample_info", select_malloc_sample_info);
2151
lua_register(L, "set_system_tenant_limit_mode", set_system_tenant_limit_mode);
2154
int APIRegister::flush()
2156
int ret = OB_SUCCESS;
2157
if (0 == print_offset_) {
2159
} else if (conn_fd_ < 0) {
2160
ret = OB_ERR_UNEXPECTED;
2162
print_buffer_[print_offset_++] = '\0';
2163
if (send(conn_fd_, print_buffer_, print_offset_, 0) < 0) {
2164
ret = OB_ERR_UNEXPECTED;
2165
OB_LOG(ERROR, "failed to send", K(errno));
2168
memset(print_buffer_, 0, print_capacity_);
2173
int APIRegister::append(const char *buffer, const int len)
2175
int ret = OB_SUCCESS;
2176
if (print_offset_ + len + 1 < print_capacity_) {
2177
strncpy(print_buffer_ + print_offset_, buffer, len);
2178
print_offset_ += len;
2179
} else if (OB_FAIL(flush())) {
2180
OB_LOG(ERROR, "failed to flush", K(ret));
2181
} else if (print_offset_ + len + 1 >= print_capacity_) {
2182
ret = OB_ARRAY_OUT_OF_RANGE;
2184
strncpy(print_buffer_ + print_offset_, buffer, len);
2185
print_offset_ += len;