oceanbase

Форк
0
/
ob_lua_api.cpp 
2188 строк · 70.3 Кб
1
/**
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.
11
 */
12

13
#include "ob_lua_api.h"
14
#include "ob_lua_handler.h"
15

16
#include <algorithm>
17
#include <bitset>
18
#include <functional>
19
#include <vector>
20

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"
42

43
#include <lua.hpp>
44

45
using namespace oceanbase;
46
using namespace common;
47
using namespace diagnose;
48
using namespace oceanbase::observer;
49
using namespace oceanbase::rpc::frame;
50
using namespace obrpc;
51
using namespace rpc;
52
using namespace sql;
53
using namespace transaction;
54

55
namespace oceanbase
56
{
57
namespace diagnose
58
{
59
class LuaAllocator : public ObIAllocator
60
{
61
public:
62
  static LuaAllocator& get_instance()
63
  {
64
    static LuaAllocator allocator;
65
    return allocator;
66
  }
67
  void *alloc(const int64_t size) override
68
  {
69
    void *ret = nullptr;
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))) {
73
#else
74
      if (MAP_FAILED == (ret = ::mmap(nullptr, size + 8, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))) {
75
        ret = nullptr;
76
      } else {
77
#endif
78
        *static_cast<uint64_t *>(ret) = size;
79
        ret = (char*)ret + 8;
80
        ObLuaHandler::get_instance().memory_update(size + 8);
81
      }
82
    }
83
    return ret;
84
  }
85
  void* alloc(const int64_t size, const ObMemAttr &attr) override
86
  {
87
    UNUSED(attr);
88
    return alloc(size);
89
  }
90
  void free(void *ptr) override
91
  {
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));
97
#else
98
      ::munmap((void *)((char *)ptr - 8), size + 8);
99
#endif
100
    }
101
  }
102
};
103
}
104

105
static ObFIFOAllocator &get_global_allocator()
106
{
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);
110
  }
111
  return allocator;
112
}
113
}
114

115
static constexpr const char *usage_str =
116
"API List:\n\n"
117
"string = usage()\n"
118
"print_to_client(arg1, arg2...)\n"
119
"int = now()\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"
145
;
146

147
class LuaVtableGenerator
148
{
149
public:
150
  LuaVtableGenerator(lua_State* L, std::vector<const char*>& columns)
151
    : stack_(L),
152
      row_id_(0),
153
      column_id_(-1),
154
      offset_(0), // dump from first row by default
155
      length_(INT_MAX), // dump all rows by default
156
      dump_(false),
157
      select_(),
158
      columns_(columns)
159
  {
160
    select_.set(); // enable all column by default
161
    if (1 == lua_gettop(stack_)) {
162
      filter();
163
    }
164
    if (dump_) {
165
      lua_pushnil(stack_);
166
    } else {
167
      lua_newtable(stack_);
168
    }
169
  }
170
  void next_row()
171
  {
172
    if (row_id_ >= offset_ && row_id_ - offset_ < length_) {
173
      if (!dump_) {
174
        lua_pushinteger(stack_, row_id_ + 1);
175
        lua_newtable(stack_);
176
      }
177
    }
178
  }
179
  void row_end()
180
  {
181
    if (row_id_ >= offset_ && row_id_ - offset_ < length_) {
182
      if (!dump_) {
183
        lua_settable(stack_, -3);
184
      } else {
185
        int ret = OB_SUCCESS;
186
        if (OB_FAIL(APIRegister::get_instance().append("\n"))) {
187
          OB_LOG(ERROR, "append failed", K(ret));
188
        }
189
      }
190
    }
191
    ++row_id_;
192
    column_id_ = -1;
193
  }
194
  void next_column()
195
  {
196
    if (in_range()) {
197
      if (!dump_) {
198
        lua_pushstring(stack_, columns_[column_id_]);
199
        lua_pushnil(stack_);
200
        lua_settable(stack_, -3);
201
      } else {
202
        int ret = OB_SUCCESS;
203
        if (OB_FAIL(APIRegister::get_instance().append("NULL "))) {
204
          OB_LOG(ERROR, "append failed", K(ret));
205
        }
206
      }
207
    }
208
  }
209
  void next_column(const char* str)
210
  {
211
    if (in_range()) {
212
      if (!dump_) {
213
        lua_pushstring(stack_, columns_[column_id_]);
214
        lua_pushstring(stack_, str);
215
        lua_settable(stack_, -3);
216
      } else {
217
        int ret = OB_SUCCESS;
218
        if (OB_FAIL(APIRegister::get_instance().append(str))) {
219
          OB_LOG(ERROR, "append failed", K(ret));
220
        }
221
        if (OB_FAIL(APIRegister::get_instance().append(" "))) {
222
          OB_LOG(ERROR, "append failed", K(ret));
223
        }
224
      }
225
    }
226
  }
227
  void next_column(bool value)
228
  {
229
    if (in_range()) {
230
      if (!dump_) {
231
        lua_pushstring(stack_, columns_[column_id_]);
232
        lua_pushboolean(stack_, value);
233
        lua_settable(stack_, -3);
234
      } else {
235
        int ret = OB_SUCCESS;
236
        if (OB_FAIL(APIRegister::get_instance().append(value ? "1 " : "0 "))) {
237
          OB_LOG(ERROR, "append failed", K(ret));
238
        }
239
      }
240
    }
241
  }
242
  void next_column(int64_t value)
243
  {
244
    if (in_range()) {
245
      if (!dump_) {
246
        lua_pushstring(stack_, columns_[column_id_]);
247
        lua_pushinteger(stack_, value);
248
        lua_settable(stack_, -3);
249
      } else {
250
        int ret = OB_SUCCESS;
251
        char buf[32];
252
        snprintf(buf, 32, "%ld ", value);
253
        if (OB_FAIL(APIRegister::get_instance().append(buf))) {
254
          OB_LOG(ERROR, "append failed", K(ret));
255
        }
256
      }
257
    }
258
  }
259
  void next_column(double value)
260
  {
261
    if (in_range()) {
262
      if (!dump_) {
263
        lua_pushstring(stack_, columns_[column_id_]);
264
        lua_pushnumber(stack_, value);
265
        lua_settable(stack_, -3);
266
      } else {
267
        int ret = OB_SUCCESS;
268
        char buf[32];
269
        snprintf(buf, 32, "%lf ", value);
270
        if (OB_FAIL(APIRegister::get_instance().append(buf))) {
271
          OB_LOG(ERROR, "append failed", K(ret));
272
        }
273
      }
274
    }
275
  }
276
  void next_column(uint64_t value)
277
  {
278
    next_column((int64_t)value);
279
  }
280
  void next_column(int32_t value)
281
  {
282
    next_column((int64_t)value);
283
  }
284
  void next_column(uint32_t value)
285
  {
286
    next_column((int64_t)value);
287
  }
288
  bool is_end()
289
  {
290
    return row_id_ - offset_ >= length_;
291
  }
292
private:
293
  void filter()
294
  {
295
    luaL_checktype(stack_, -1, LUA_TTABLE);
296
    lua_pushnil(stack_);
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);
302
        lua_pushnil(stack_);
303
        select_.reset();
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)) {
309
              select_.set(i);
310
            }
311
          }
312
          lua_pop(stack_, 1);
313
        }
314
      } else if (0 == strcmp(key, "limit")) {
315
        luaL_checktype(stack_, -1, LUA_TTABLE);
316
        lua_pushnil(stack_);
317
        if (lua_next(stack_, -2) != 0) {
318
          offset_ = lua_tointeger(stack_, -1);
319
          lua_pop(stack_, 1);
320
          if (lua_next(stack_, -2) != 0) {
321
            length_ = lua_tointeger(stack_, -1);
322
            lua_pop(stack_, 2);
323
          } else {
324
            length_ = offset_;
325
            offset_ = 0;
326
          }
327
        }
328
      } else if (0 == strcmp(key, "dump")) {
329
        luaL_checktype(stack_, -1, LUA_TBOOLEAN);
330
        if (0 != lua_toboolean(stack_, -1)) {
331
          dump_ = true;
332
        }
333
      } else {
334
        OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "invalid arguments", K(key));
335
      }
336
      lua_pop(stack_, 1);
337
    }
338
    lua_pop(stack_, 1);
339
  }
340
  bool in_range()
341
  {
342
    return row_id_ >= offset_ && row_id_ - offset_ < length_ && select_[++column_id_];
343
  }
344
private:
345
  lua_State* stack_;
346
  int row_id_;
347
  int column_id_;
348
  int offset_;
349
  int length_;
350
  bool dump_;
351
  std::bitset<256> select_;
352
  std::vector<const char*>& columns_;
353
};
354

355
/**
356
 * All API need to use the following format.
357
 * int xxx(lua_State* L), which return the count of return values.
358
 *
359
 * lua API for reference: http://www.lua.org/manual/5.4/
360
 **/
361

362
// string = usage()
363
int usage(lua_State* L)
364
{
365
  int argc = lua_gettop(L);
366
  if (0 != argc) {
367
    OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call usage() failed, bad arguments count, should be 0.");
368
    lua_pushnil(L);
369
  } else {
370
    lua_pushstring(L, usage_str);
371
  }
372
  return 1;
373
}
374

375
// print_to_client(arg1, arg2...)
376
int print_to_client(lua_State* L)
377
{
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)) {
382
      size_t len = 0;
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));
386
      }
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));
391
        }
392
      } else {
393
        if (OB_FAIL(APIRegister::get_instance().append("1"))) {
394
          OB_LOG(ERROR, "append failed", K(ret));
395
        }
396
      }
397
    } else if (lua_islightuserdata(L, i)) {
398
      void *ptr = lua_touserdata(L, i);
399
      char buf[65];
400
      snprintf(buf, sizeof(buf), "%p", ptr);
401
      if (OB_FAIL(APIRegister::get_instance().append(buf))) {
402
        OB_LOG(ERROR, "append failed", K(ret));
403
      }
404
    } else if (lua_isnil(L, i)) {
405
      ret = APIRegister::get_instance().append("NULL");
406
    } else {
407
      OB_LOG(ERROR, "arg was not convertible", K(i));
408
    }
409
    APIRegister::get_instance().append(" ");
410
  }
411
  APIRegister::get_instance().append("\n");
412
  return 0;
413
}
414

415
// int = now()
416
int now(lua_State* L)
417
{
418
  int argc = lua_gettop(L);
419
  if (0 != argc) {
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);
422
  } else {
423
    lua_pushinteger(L, common::ObTimeUtility::fast_current_time());
424
  }
425
  return 1;
426
}
427

428
// list = get_tenant_id_list()
429
int get_tenant_id_list(lua_State* L)
430
{
431
  int argc = lua_gettop(L);
432
  if (0 != argc) {
433
    OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call get_tenant_id_list() failed, bad arguments count, should be 0.");
434
  } else {
435
    lua_newtable(L);
436
    uint64_t *tenant_ids = nullptr;
437
    int count = 0;
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);
440
    }
441
    for (int64_t i = 0; i < count; ++i) {
442
      lua_pushinteger(L, i + 1);
443
      lua_pushinteger(L, tenant_ids[i]);
444
      lua_settable(L, -3);
445
    }
446
    diagnose::free(tenant_ids);
447
  }
448
  return 1;
449
}
450

451
// int = get_tenant_mem_limit(int)
452
int get_tenant_mem_limit(lua_State* L)
453
{
454
  int argc = lua_gettop(L);
455
  if (1 != argc) {
456
    OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call get_tenant_mem_limit() failed, bad arguments count, should be 1.");
457
  } else {
458
    luaL_checktype(L, 1, LUA_TNUMBER);
459
    lua_pushinteger(L, ObMallocAllocator::get_instance()->get_tenant_limit(lua_tointeger(L, 1)));
460
  }
461
  return 1;
462
}
463

464
int get_tenant_parameter(lua_State* L)
465
{
466
  // TODO
467
  lua_pushnil(L);
468
  return 1;
469
}
470

471
// forward declaration
472
int get_tenant_sysstat(int64_t tenant_id, int64_t stat_id, int64_t &value);
473

474
// int = get_tenant_sysstat_by_id(int, int)
475
int get_tenant_sysstat_by_id(lua_State* L)
476
{
477
  int ret = OB_SUCCESS;
478
  int argc = lua_gettop(L);
479
  if (2 != argc) {
480
    OB_LOG(ERROR, "call get_tenant_sysstat_by_id() failed, bad arguments count, should be 2.");
481
    ret = OB_INVALID_ARGUMENT;
482
  } else {
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);
487
    int64_t value = 0;
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));
492
        } else {
493
          lua_pushinteger(L, value);
494
        }
495
        break;
496
      }
497
    }
498
  }
499
  if (OB_FAIL(ret)) {
500
    lua_pushnil(L);
501
  }
502
  return 1;
503
}
504

505
// int = get_tenant_sysstat_by_name(int, string)
506
int get_tenant_sysstat_by_name(lua_State* L)
507
{
508
  int ret = OB_SUCCESS;
509
  int argc = lua_gettop(L);
510
  if (2 != argc) {
511
    OB_LOG(ERROR, "call get_tenant_sysstat_by_name() failed, bad arguments count, should be 2.");
512
    ret = OB_INVALID_ARGUMENT;
513
  } else {
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);
518
    int64_t value = 0;
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));
524
        } else {
525
          lua_pushinteger(L, value);
526
        }
527
        break;
528
      }
529
    }
530
  }
531
  if (OB_FAIL(ret)) {
532
    lua_pushnil(L);
533
  }
534
  return 1;
535
}
536

537
int summary_each_eio_info(char *buf, int &pos, int buf_len, easy_io_t *eio, const char *rpc_des);
538

539
int get_easy_diagnose_info(lua_State* L)
540
{
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) {
545
    lua_pushnil(L);
546
  } else {
547
    int pos = 0;
548
    const int summary_len = 48 * 1024;
549
    HEAP_VAR(ByteBuf<summary_len>, summary) {
550
      memset(summary, 0, sizeof(summary));
551

552
      eio = net_easy->get_rpc_eio();
553
      ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "rpc_eio:\n");
554

555
      eio = net_easy->get_batch_rpc_eio();
556
      if (OB_SUCC(ret)) {
557
        ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "batch_rpc_eio:\n");
558
      }
559

560
      eio = net_easy->get_high_prio_eio();
561
      if (OB_SUCC(ret)) {
562
        ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "high_prio_rpc_eio:\n");
563
      }
564

565
      eio = net_easy->get_mysql_eio();
566
      if (OB_SUCC(ret)) {
567
        ret = summary_each_eio_info(summary, pos, sizeof(summary), eio, "my_sql_rpc_eio:\n");
568
      }
569

570
      lua_pushstring(L, (const char*) summary);
571
    }
572
  }
573

574
  return 1;
575
}
576

577
int get_tenant_pcode_statistics(lua_State* L)
578
{
579
  int ret = OB_SUCCESS;
580
  int argc = lua_gettop(L);
581
  if (1 != argc) {
582
    OB_LOG(ERROR, "call get_tenant_pcode_statistics() failed, bad arguments count, should be 1.");
583
    ret = OB_INVALID_ARGUMENT;
584
  } else {
585
    luaL_checktype(L, 1, LUA_TNUMBER);
586
    int tenant_id = lua_tointeger(L, 1);
587
    ObRpcPacketSet &set = ObRpcPacketSet::instance();
588
    RpcStatItem item;
589
    char *pcode_name = nullptr;
590
    int64_t dcount = 0;
591
    HEAP_VAR(ByteBuf<64 * ObRpcPacketSet::THE_PCODE_COUNT>, output) {
592
      char str[64] = {0};
593
      int pos = 0;
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))) {
596
          // continue
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));
601
          pos += strlen(str);
602
        }
603
      }
604
      lua_pushstring(L, (const char*)output);
605
    }
606
  }
607
  if (OB_FAIL(ret)) {
608
    lua_pushnil(L);
609
  }
610
  return 1;
611
}
612

613
// int = set_log_probe(string)
614
int set_log_probe(lua_State* L)
615
{
616
  int ret = OB_SUCCESS;
617
  int argc = lua_gettop(L);
618
  if (1 != argc) {
619
    OB_LOG(ERROR, "call set_log_probe() failed, bad arguments count, should be 1.");
620
    ret = OB_INVALID_ARGUMENT;
621
  } else {
622
    luaL_checktype(L, 1, LUA_TSTRING);
623
    size_t len = 0;
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));
630
    } else {
631
      memcpy(ptr, arg, len);
632
      ptr[len] = '\0';
633
      int probe_cnt = OB_LOGGER.set_probe(ptr);
634
      lua_pushinteger(L, probe_cnt);
635
    }
636
  }
637
  if (OB_FAIL(ret)) {
638
    lua_pushinteger(L, -1);
639
  }
640
  return 1;
641
}
642

643
// string = show_log_probe()
644
int show_log_probe(lua_State* L)
645
{
646
  int argc = lua_gettop(L);
647
  if (0 != argc) {
648
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call show_log_probe() failed, bad arguments count, should be 0.");
649
  } else {
650
    lua_pushstring(L, OB_LOGGER.show_probe());
651
  }
652
  return 1;
653
}
654

655
// list{list, list...} = select_processlist()
656
int select_processlist(lua_State* L)
657
{
658
  class GetProcess
659
  {
660
  public:
661
    GetProcess(LuaVtableGenerator& gen) : gen_(gen) {}
662
    bool operator()(sql::ObSQLSessionMgr::Key key, ObSQLSessionInfo *sess_info)
663
    {
664
      constexpr int64_t BUF_LEN = (1 << 10);
665
      char buf[BUF_LEN];
666
      gen_.next_row();
667
      // id
668
      gen_.next_column(static_cast<uint64_t>(key.sessid_));
669
      // user
670
      if (sess_info->get_is_deserialized()) {
671
        gen_.next_column();
672
      } else {
673
        UNUSED(sess_info->get_user_name().to_string(buf, BUF_LEN));
674
        gen_.next_column(buf);
675
      }
676
      // tenant
677
      UNUSED(sess_info->get_tenant_name().to_string(buf, BUF_LEN));
678
      gen_.next_column(buf);
679
      // host
680
      UNUSED(sess_info->get_peer_addr().ip_port_to_string(buf, BUF_LEN));
681
      gen_.next_column(buf);
682
      // db
683
      if (0 == sess_info->get_database_name().length()) {
684
        gen_.next_column();
685
      } else {
686
        UNUSED(sess_info->get_database_name().to_string(buf, BUF_LEN));
687
        gen_.next_column(buf);
688
      }
689
      // command
690
      gen_.next_column(sess_info->get_mysql_cmd_str());
691
      // sql_id
692
      {
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);
699
        } else {
700
          sql_id[0] = '\0';
701
        }
702
        gen_.next_column(sql_id);
703
      }
704
      // time
705
      gen_.next_column((::oceanbase::common::ObTimeUtility::current_time() - sess_info->get_cur_state_start_time()) / 1000000);
706
      // state
707
      gen_.next_column(sess_info->get_session_state_str());
708
      // info
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);
715
      } else {
716
        gen_.next_column();
717
      }
718
      // sql_port
719
      gen_.next_column(GCONF.mysql_port);
720
      // proxy_sessid
721
      if (ObBasicSessionInfo::VALID_PROXY_SESSID == sess_info->get_proxy_sessid()) {
722
        gen_.next_column();
723
      } else {
724
        gen_.next_column(sess_info->get_proxy_sessid());
725
      }
726
      // master_sessid
727
      if (ObBasicSessionInfo::INVALID_SESSID == sess_info->get_master_sessid()) {
728
        gen_.next_column();
729
      } else {
730
        gen_.next_column(sess_info->get_master_sessid());
731
      }
732
      // user_client_ip
733
      if (sess_info->get_client_ip().empty()) {
734
        gen_.next_column();
735
      } else {
736
        UNUSED(sess_info->get_client_ip().to_string(buf, BUF_LEN));
737
        gen_.next_column(buf);
738
      }
739
      // user_host
740
      if (sess_info->get_host_name().empty()) {
741
        gen_.next_column();
742
      } else {
743
        UNUSED(sess_info->get_host_name().to_string(buf, BUF_LEN));
744
        gen_.next_column(buf);
745
      }
746
      // trans_id
747
      uint64_t tx_id = sess_info->get_tx_id();
748
      gen_.next_column(tx_id);
749
      // thread_id
750
      gen_.next_column(static_cast<uint64_t>(sess_info->get_thread_id()));
751
      // ssl_cipher
752
      if (sess_info->get_ssl_cipher().empty()) {
753
        gen_.next_column();
754
      } else {
755
        UNUSED(sess_info->get_ssl_cipher().to_string(buf, BUF_LEN));
756
        gen_.next_column(buf);
757
      }
758
      // trace_id
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);
765
      } else {
766
        gen_.next_column();
767
      }
768
      // trans_state
769
      if (sess_info->is_in_transaction()) {
770
        gen_.next_column(sess_info->get_tx_desc()->get_tx_state_str());
771
      } else {
772
        gen_.next_column();
773
      }
774
      // total_time
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);
779
      } else {
780
        int64_t time_sec = (::oceanbase::common::ObTimeUtility::current_time() - sess_info->get_cur_state_start_time()) / 1000000;
781
        gen_.next_column(time_sec);
782
      }
783
      // retry_cnt
784
      gen_.next_column(sess_info->get_retry_info().get_retry_cnt());
785
      // retry_info
786
      gen_.next_column(sess_info->get_retry_info().get_last_query_retry_err());
787
      // action
788
      gen_.next_column(sess_info->get_action_name());
789
      // module
790
      gen_.next_column(sess_info->get_module_name());
791
      // client_info
792
      gen_.next_column(sess_info->get_client_info());
793

794
      gen_.row_end();
795
      return !gen_.is_end();
796
    }
797
  private:
798
    LuaVtableGenerator& gen_;
799
  };
800

801
  int ret = OB_SUCCESS;
802
  int argc = lua_gettop(L);
803
  if (argc > 1) {
804
    OB_LOG(ERROR, "call select_processlist() failed, bad arguments count, should be less than 2.");
805
    lua_pushnil(L);
806
  } else {
807
    std::vector<const char*> columns = {
808
      "id",
809
      "user",
810
      "tenant",
811
      "host",
812
      "db",
813
      "command",
814
      "sql_id",
815
      "time",
816
      "state",
817
      "info",
818
      "sql_port",
819
      "proxy_sessid",
820
      "master_sessid",
821
      "user_client_ip",
822
      "user_host",
823
      "trans_id",
824
      "thread_id",
825
      "ssl_cipher",
826
      "trace_id",
827
      "trans_state",
828
      "total_time",
829
      "retry_cnt",
830
      "retry_info",
831
      "action",
832
      "module",
833
      "client_info"
834
    };
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));
839
    }
840
  }
841
  return 1;
842
}
843

844
// list{list, list...} = select_sysstat()
845
int select_sysstat(lua_State* L)
846
{
847
  int ret = OB_SUCCESS;
848
  int argc = lua_gettop(L);
849
  if (argc > 1) {
850
    OB_LOG(ERROR, "call select_sysstat() failed, bad arguments count, should be less than 2.");
851
    lua_pushnil(L);
852
  } else {
853
    common::ObVector<uint64_t> ids;
854
    std::vector<const char*> columns = {
855
      "tenant_id",
856
      "statistic",
857
      "value",
858
      "value_type",
859
      "stat_id",
860
      "name",
861
      "class",
862
      "can_visible"
863
    };
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));
873
        } else {
874
          for (int64_t stat_idx = 0;
875
               stat_idx < ObStatEventIds::STAT_EVENT_SET_END && !gen.is_end();
876
               ++stat_idx) {
877
            if (ObStatEventIds::STAT_EVENT_ADD_END == stat_idx) {
878
              // do nothing
879
            } else {
880
              gen.next_row();
881
              // tenant_id
882
              gen.next_column(ids.at(i));
883
              // statistic
884
              {
885
                if (stat_idx < ObStatEventIds::STAT_EVENT_ADD_END) {
886
                  gen.next_column(stat_idx);
887
                } else {
888
                  gen.next_column(stat_idx - 1);
889
                }
890
              }
891
              // value
892
              {
893
                if (stat_idx < ObStatEventIds::STAT_EVENT_ADD_END) {
894
                  if (OB_ISNULL(diag_info.get_add_stat_stats().get(stat_idx))) {
895
                    gen.next_column();
896
                    OB_LOG(ERROR, "invalid argument", K(stat_idx), K(ids.at(i)));
897
                  } else {
898
                    gen.next_column(diag_info.get_add_stat_stats().get(stat_idx)->stat_value_);
899
                  }
900
                } else {
901
                  if (OB_ISNULL(diag_info.get_set_stat_stats().get(stat_idx - ObStatEventIds::STAT_EVENT_ADD_END - 1))) {
902
                    gen.next_column();
903
                    OB_LOG(ERROR, "invalid argument", K(stat_idx), K(ids.at(i)));
904
                  } else {
905
                    gen.next_column(diag_info.get_set_stat_stats().get(stat_idx - ObStatEventIds::STAT_EVENT_ADD_END - 1)->stat_value_);
906
                  }
907
                }
908
              }
909
              // value_type
910
              {
911
                if (stat_idx < ObStatEventIds::STAT_EVENT_ADD_END) {
912
                  gen.next_column("ADD_VALUE");
913
                } else {
914
                  gen.next_column("SET_VALUE");
915
                }
916
              }
917
              // stat_id
918
              gen.next_column(OB_STAT_EVENTS[stat_idx].stat_id_);
919
              // name
920
              gen.next_column(OB_STAT_EVENTS[stat_idx].name_);
921
              // class
922
              gen.next_column(OB_STAT_EVENTS[stat_idx].stat_class_);
923
              // can_visible
924
              gen.next_column(OB_STAT_EVENTS[stat_idx].can_visible_);
925

926
              gen.row_end();
927
            }
928
          }
929
        }
930
      }
931
    }
932
  }
933
  return 1;
934
}
935

936
// list{list, list...} = select_memory_info()
937
int select_memory_info(lua_State *L)
938
{
939
  int ret = OB_SUCCESS;
940
  int argc = lua_gettop(L);
941
  if (argc > 1) {
942
    OB_LOG(ERROR, "call select_memory_info() failed, bad arguments count, should be less than 2.");
943
    lua_pushnil(L);
944
  } else {
945
    uint64_t *tenant_ids = nullptr;
946
    std::vector<const char*> columns = {
947
      "tenant_id",
948
      "ctx_id",
949
      "ctx_name",
950
      "label",
951
      "hold",
952
      "used",
953
      "count"
954
    };
955
    LuaVtableGenerator gen(L, columns);
956
    int tenant_cnt = 0;
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);
959
    }
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);
964
        if (nullptr == ta) {
965
          ta = ObMallocAllocator::get_instance()->get_tenant_ctx_allocator_unrecycled(tenant_id,
966
                                                                                      ctx_id);
967
        }
968
        if (nullptr == ta) {
969
          // do nothing
970
        } else {
971
          IGNORE_RETURN ta->iter_label([&](lib::ObLabel &label, LabelItem *l_item)
972
          {
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_;
977

978
            gen.next_row();
979
            // tenant_id
980
            gen.next_column(tenant_id);
981
            // ctx_id
982
            gen.next_column(ctx_id);
983
            // ctx_name
984
            gen.next_column(get_global_ctx_info().get_ctx_name(ctx_id));
985
            // label
986
            gen.next_column(mod_name);
987
            // hold
988
            gen.next_column(hold);
989
            // used
990
            gen.next_column(used);
991
            // count
992
            gen.next_column(count);
993

994
            gen.row_end();
995
            return OB_SUCCESS;
996
          });
997
        }
998
      }
999
    }
1000

1001
    diagnose::free(tenant_ids);
1002
  }
1003
  return 1;
1004
}
1005

1006
// list{list, list...} = select_tenant_ctx_memory_info()
1007
int select_tenant_ctx_memory_info(lua_State *L)
1008
{
1009
  int argc = lua_gettop(L);
1010
  if (argc > 1) {
1011
    OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call select_tenant_ctx_memory_info() failed, bad arguments count, should be less than 2.");
1012
    lua_pushnil(L);
1013
  } else {
1014
    uint64_t *tenant_ids = nullptr;
1015
    int tenant_cnt = 0;
1016
    std::vector<const char*> columns = {
1017
      "tenant_id",
1018
      "ctx_id",
1019
      "ctx_name",
1020
      "hold",
1021
      "used",
1022
      "limit"
1023
    };
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);
1027
    }
1028

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,
1035
                                                                                      ctx_id);
1036
        }
1037
        if (nullptr == ta) {
1038
          // do nothing
1039
        } else {
1040
          gen.next_row();
1041

1042
          // tenant_id
1043
          gen.next_column(tenant_id);
1044
          // ctx_id
1045
          gen.next_column(ctx_id);
1046
          // ctx_name
1047
          gen.next_column(get_global_ctx_info().get_ctx_name(ctx_id));
1048
          // hold
1049
          gen.next_column(ta->get_hold());
1050
          // used
1051
          gen.next_column(ta->get_used());
1052
          // limit
1053
          gen.next_column(ta->get_limit());
1054

1055
          gen.row_end();
1056
        }
1057
      }
1058
    }
1059

1060
    diagnose::free(tenant_ids);
1061
  }
1062
  return 1;
1063
}
1064

1065
// list{list, list...} = select_trans_stat()
1066
int select_trans_stat(lua_State *L)
1067
{
1068
  int ret = OB_SUCCESS;
1069
  int argc = lua_gettop(L);
1070
  ObTransService *trans_service = nullptr;
1071
  ObArray<uint64_t> tenant_ids;
1072
  ObTxStat tx_stat;
1073
  if (argc > 1) {
1074
    OB_LOG(ERROR, "call select_trans_stat() failed, bad arguments count, should be 0.");
1075
    lua_pushnil(L);
1076
  } else if (OB_ISNULL(GCTX.omt_)) {
1077
    OB_LOG(ERROR, "omt is nullptr");
1078
    lua_pushnil(L);
1079
  } else if (OB_FAIL(GCTX.omt_->get_mtl_tenant_ids(tenant_ids))) {
1080
    OB_LOG(ERROR, "failed to get tenant_ids", K(ret));
1081
    lua_pushnil(L);
1082
  } else {
1083
    HEAP_VAR(ObTxStatIterator, iter) {
1084
      iter.reset();
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));
1091
          }
1092
        }
1093
      }
1094
      if (OB_FAIL(ret)) {
1095
        lua_pushnil(L);
1096
      } else if (OB_FAIL(iter.set_ready())) {
1097
        OB_LOG(ERROR, "ObTxStatIterator set ready error", K(ret));
1098
        lua_pushnil(L);
1099
      } else {
1100
        ret = iter.get_next(tx_stat);
1101
      }
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 = {
1105
        "tenant_id",
1106
        "tx_type",
1107
        "tx_id",
1108
        "session_id",
1109
        "scheduler_addr",
1110
        "is_decided",
1111
        "ls_id",
1112
        "participants",
1113
        "tx_ctx_create_time",
1114
        "expired_time",
1115
        "ref_cnt",
1116
        "last_op_sn",
1117
        "pending_write",
1118
        "state",
1119
        "part_tx_action",
1120
        "tx_ctx_addr",
1121
        "mem_ctx_id",
1122
        "pending_log_size",
1123
        "flushed_log_size",
1124
        "role_state",
1125
        "is_exiting",
1126
        "coord",
1127
        "last_request_ts",
1128
        "gtrid",
1129
        "bqual",
1130
        "format_id"
1131
      };
1132
      LuaVtableGenerator gen(L, columns);
1133
      while (OB_SUCC(ret) && !gen.is_end()) {
1134
        gen.next_row();
1135
        // tenant_id
1136
        gen.next_column(tx_stat.tenant_id_);
1137
        // tx_type
1138
        gen.next_column(tx_stat.tx_type_);
1139
        // tx_id
1140
        gen.next_column(tx_stat.tx_id_.get_id());
1141
        // session_id
1142
        gen.next_column(tx_stat.session_id_);
1143
        // scheduler_addr
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);
1147
        // is_decided
1148
        gen.next_column(tx_stat.has_decided_);
1149
        // ls_id
1150
        gen.next_column(tx_stat.ls_id_.id());
1151
        // participants
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);
1156
        } else {
1157
          ret = iter.get_next(tx_stat);
1158
        }
1159
        // tx_ctx_create_time
1160
        gen.next_column(tx_stat.tx_ctx_create_time_);
1161
        // expired_time
1162
        gen.next_column(tx_stat.tx_expired_time_);
1163
        // ref_cnt
1164
        gen.next_column(tx_stat.ref_cnt_);
1165
        // last_op_sn
1166
        gen.next_column(tx_stat.last_op_sn_);
1167
        // pending_write
1168
        gen.next_column(tx_stat.pending_write_);
1169
        // state
1170
        gen.next_column(tx_stat.state_);
1171
        // part_tx_action
1172
        gen.next_column(tx_stat.part_tx_action_);
1173
        // tx_ctx_addr
1174
        gen.next_column((uint64_t)tx_stat.tx_ctx_addr_);
1175
        // mem_ctx_id
1176
        gen.next_column(-1);
1177
        // pending_log_size
1178
        gen.next_column(tx_stat.pending_log_size_);
1179
        // flushed_log_size
1180
        gen.next_column(tx_stat.flushed_log_size_);
1181
        // role_state
1182
        gen.next_column(tx_stat.role_state_);
1183
        // is_exiting
1184
        gen.next_column(tx_stat.is_exiting_);
1185
        // coord
1186
        gen.next_column(tx_stat.coord_.id());
1187
        // last_request_ts
1188
        gen.next_column(tx_stat.last_request_ts_);
1189
        // gtrid
1190
        gen.next_column(tx_stat.xid_.get_gtrid_str());
1191
        // bqual
1192
        gen.next_column(tx_stat.xid_.get_bqual_str());
1193
        // format_id
1194
        gen.next_column(tx_stat.xid_.get_format_id());
1195

1196
        gen.row_end();
1197
        ret = iter.get_next(tx_stat);
1198
      }
1199
    }
1200
    if (OB_FAIL(ret) && OB_ITER_END != ret) {
1201
      OB_LOG(ERROR, "iter failed", K(ret));
1202
    }
1203
  }
1204
  return 1;
1205
}
1206

1207
// list{list, list...} = select_sql_workarea_active()
1208
int select_sql_workarea_active(lua_State *L)
1209
{
1210
  int ret = OB_SUCCESS;
1211
  int argc = lua_gettop(L);
1212
  if (argc > 1) {
1213
    OB_LOG(ERROR, "call select_sql_workarea_active() failed, bad arguments count, should be less than 2.");
1214
    lua_pushnil(L);
1215
  } else if (OB_ISNULL(GCTX.omt_)) {
1216
    OB_LOG(ERROR, "GCTX.omt_ is NULL");
1217
    lua_pushnil(L);
1218
  } else {
1219
    ObArray<uint64_t> ids;
1220
    common::ObSEArray<sql::ObSqlWorkareaProfileInfo, 32> wa_actives;
1221
    std::vector<const char*> columns = {
1222
      "plan_id",
1223
      "sql_id",
1224
      "sql_exec_id",
1225
      "operation_type",
1226
      "operation_id",
1227
      "sid",
1228
      "active_time",
1229
      "work_area_size",
1230
      "expect_size",
1231
      "actual_mem_used",
1232
      "max_mem_used",
1233
      "number_passes",
1234
      "tempseg_size",
1235
      "tenant_id",
1236
      "policy"
1237
    };
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];
1242
      wa_actives.reset();
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));
1247
        }
1248
      }
1249
      for (int64_t j = 0; j < wa_actives.count() && !gen.is_end(); ++j) {
1250
        auto &wa_active = wa_actives[j];
1251
        gen.next_row();
1252
        // plan_id
1253
        gen.next_column(wa_active.plan_id_);
1254
        // sql_id
1255
        gen.next_column(wa_active.sql_id_);
1256
        // sql_exec_id
1257
        gen.next_column(wa_active.sql_exec_id_);
1258
        // operation_type
1259
        gen.next_column(get_phy_op_name(wa_active.profile_.get_operator_type()));
1260
        // operation_id
1261
        gen.next_column(wa_active.profile_.get_operator_id());
1262
        // sid
1263
        gen.next_column(wa_active.session_id_);
1264
        // active_time
1265
        gen.next_column(ObTimeUtility::current_time() - wa_active.profile_.get_active_time());
1266
        // work_area_size
1267
        gen.next_column(wa_active.profile_.get_cache_size());
1268
        // expected_size
1269
        gen.next_column(wa_active.profile_.get_expect_size());
1270
        // actual_mem_used
1271
        gen.next_column(wa_active.profile_.get_mem_used());
1272
        // max_mem_used
1273
        gen.next_column(wa_active.profile_.get_max_mem_used());
1274
        // number_passes
1275
        gen.next_column(wa_active.profile_.get_number_pass());
1276
        // tempseg_size
1277
        gen.next_column(wa_active.profile_.get_dumped_size());
1278
        // tenant_id
1279
        gen.next_column(tenant_id);
1280
        // policy
1281
        if (wa_active.profile_.get_auto_policy()) {
1282
          gen.next_column(EXECUTION_AUTO_POLICY);
1283
        } else {
1284
          gen.next_column(EXECUTION_MANUAL_POLICY);
1285
        }
1286

1287
        gen.row_end();
1288
      }
1289
    }
1290
  }
1291
  return 1;
1292
}
1293

1294
// list{list, list...} = select_sys_task_status()
1295
int select_sys_task_status(lua_State *L)
1296
{
1297
  int ret = OB_SUCCESS;
1298
  int argc = lua_gettop(L);
1299
  HEAP_VAR(share::ObSysStatMgrIter, iter) {
1300
    if (argc > 1) {
1301
      OB_LOG(ERROR, "call select_sys_task_status() failed, bad arguments count, should be less than 2.");
1302
      lua_pushnil(L);
1303
    } else if (OB_FAIL(SYS_TASK_STATUS_MGR.get_iter(iter))) {
1304
      OB_LOG(ERROR, "failed to get iter", K(ret));
1305
      lua_pushnil(L);
1306
    } else if (!iter.is_ready()) {
1307
      OB_LOG(ERROR, "iter not ready");
1308
    } else {
1309
      share::ObSysTaskStat status;
1310
      std::vector<const char*> columns = {
1311
        "start_time",
1312
        "task_type",
1313
        "task_id",
1314
        "tenant_id",
1315
        "comment",
1316
        "is_cancel"
1317
      };
1318
      LuaVtableGenerator gen(L, columns);
1319
      while (OB_SUCC(iter.get_next(status)) && !gen.is_end()) {
1320
        gen.next_row();
1321
        // start_time
1322
        gen.next_column(status.start_time_);
1323
        // task_type
1324
        gen.next_column(sys_task_type_to_str(status.task_type_));
1325
        // task_id
1326
        {
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");
1331
            gen.next_column();
1332
          } else {
1333
            gen.next_column(task_id);
1334
          }
1335
        }
1336
        // tenant_id
1337
        gen.next_column(status.tenant_id_);
1338
        // comment
1339
        gen.next_column(status.comment_);
1340
        // is_cancel
1341
        gen.next_column(status.is_cancel_);
1342

1343
        gen.row_end();
1344
      }
1345
    }
1346
  }
1347
  return 1;
1348
}
1349

1350
// list{list, list...} = select_dump_tenant_info()
1351
int select_dump_tenant_info(lua_State *L)
1352
{
1353
  int ret = OB_SUCCESS;
1354
  int argc = lua_gettop(L);
1355
  auto *omt = GCTX.omt_;
1356
  if (argc > 1) {
1357
    OB_LOG(ERROR, "call select_dump_tenant_info() failed, bad arguments count, should be less than 2.");
1358
    lua_pushnil(L);
1359
  } else if (OB_ISNULL(omt)) {
1360
    OB_LOG(ERROR, "omt is nullptr");
1361
    lua_pushnil(L);
1362
  } else {
1363
    auto *omt = GCTX.omt_;
1364
    std::vector<const char*> columns = {
1365
      "tenant_id",
1366
      "compat_mode",
1367
      "unit_min_cpu",
1368
      "unit_max_cpu",
1369
      "slice",
1370
      "remain_slice",
1371
      "token_cnt",
1372
      "ass_token_cnt",
1373
      "lq_tokens",
1374
      "used_lq_tokens",
1375
      "stopped",
1376
      "idle_us",
1377
      "recv_hp_rpc_cnt",
1378
      "recv_np_rpc_cnt",
1379
      "recv_lp_rpc_cnt",
1380
      "recv_mysql_cnt",
1381
      "recv_task_cnt",
1382
      "recv_large_req_cnt",
1383
      "recv_large_queries",
1384
      "actives",
1385
      "workers",
1386
      "lq_warting_workers",
1387
      "req_queue_total_size",
1388
      "queue_0",
1389
      "queue_1",
1390
      "queue_2",
1391
      "queue_3",
1392
      "queue_4",
1393
      "queue_5",
1394
      "large_queued"
1395
    };
1396
    LuaVtableGenerator gen(L, columns);
1397
    auto func = [&] (omt::ObTenant &t) {
1398
      gen.next_row();
1399
      // tenant_id
1400
      gen.next_column(t.id_);
1401
      // compat_mode
1402
      gen.next_column(static_cast<int64_t>(t.get_compat_mode()));
1403
      // unit_min_cpu
1404
      gen.next_column(t.unit_min_cpu_);
1405
      // unit_max_cpu
1406
      gen.next_column(t.unit_max_cpu_);
1407
      // slice
1408
      gen.next_column(0);
1409
      // remain_slice
1410
      gen.next_column(0);
1411
      // token_cnt
1412
      gen.next_column(t.worker_count());
1413
      // ass_token_cnt
1414
      gen.next_column(t.worker_count());
1415
      // lq_tokens
1416
      gen.next_column(0);
1417
      // used_lq_tokens
1418
      gen.next_column(0);
1419
      // stopped
1420
      gen.next_column(t.stopped_);
1421
      // idle_us
1422
      gen.next_column(0);
1423
      // recv_hp_rpc_cnt
1424
      gen.next_column(t.recv_hp_rpc_cnt_);
1425
      // recv_np_rpc_cnt
1426
      gen.next_column(t.recv_np_rpc_cnt_);
1427
      // recv_lp_rpc_cnt
1428
      gen.next_column(t.recv_lp_rpc_cnt_);
1429
      // recv_mysql_cnt
1430
      gen.next_column(t.recv_mysql_cnt_);
1431
      // recv_task_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_);
1437
      // actives
1438
      gen.next_column(t.workers_.get_size());
1439
      // workers
1440
      gen.next_column(t.workers_.get_size());
1441
      // lq_warting_workers
1442
      gen.next_column(0);
1443
      // req_queue_total_size
1444
      gen.next_column(t.req_queue_.size());
1445
      // queue_0
1446
      gen.next_column(t.req_queue_.queue_size(0));
1447
      // queue_1
1448
      gen.next_column(t.req_queue_.queue_size(1));
1449
      // queue_2
1450
      gen.next_column(t.req_queue_.queue_size(2));
1451
      // queue_3
1452
      gen.next_column(t.req_queue_.queue_size(3));
1453
      // queue_4
1454
      gen.next_column(t.req_queue_.queue_size(4));
1455
      // queue_5
1456
      gen.next_column(t.req_queue_.queue_size(5));
1457
      // large_queued
1458
      gen.next_column(t.lq_retry_queue_size());
1459
      gen.row_end();
1460
      return OB_SUCCESS;
1461
    };
1462
    if (OB_FAIL(omt->for_each(func))) {
1463
      OB_LOG(ERROR, "omt for each failed", K(ret));
1464
    }
1465
  }
1466
  return 1;
1467
}
1468

1469
// list{list, list...} = select_disk_stat()
1470
int select_disk_stat(lua_State *L)
1471
{
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;
1476
  if (argc > 1) {
1477
    OB_LOG(ERROR, "call select_disk_stat() failed, bad arguments count, should be less than 2.");
1478
    lua_pushnil(L);
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));
1482
    lua_pushnil(L);
1483
  } else {
1484
    std::vector<const char*> columns = {
1485
      "total_size",
1486
      "used_size",
1487
      "free_size",
1488
      "is_disk_valid",
1489
      "disk_error_begin_ts"
1490
    };
1491
    LuaVtableGenerator gen(L, columns);
1492
    gen.next_row();
1493

1494
    // total_size
1495
    gen.next_column(OB_SERVER_BLOCK_MGR.get_total_macro_block_count() * OB_SERVER_BLOCK_MGR.get_macro_block_size());
1496
    // used_size
1497
    gen.next_column(OB_SERVER_BLOCK_MGR.get_used_macro_block_count() * OB_SERVER_BLOCK_MGR.get_macro_block_size());
1498
    // free_size
1499
    gen.next_column(OB_SERVER_BLOCK_MGR.get_free_macro_block_count() * OB_SERVER_BLOCK_MGR.get_macro_block_size());
1500
    // is_disk_valid
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);
1504

1505
    gen.row_end();
1506
  }
1507
  return 1;
1508
}
1509

1510
// list{list, list...} = select_tenant_memory_info()
1511
int select_tenant_memory_info(lua_State *L)
1512
{
1513
  int argc = lua_gettop(L);
1514
  if (argc > 1) {
1515
    OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "call select_tenant_memory_info() failed, bad arguments count, should be less than 2.");
1516
    lua_pushnil(L);
1517
  } else {
1518
    uint64_t *tenant_ids = nullptr;
1519
    int tenant_cnt = 0;
1520
    std::vector<const char*> columns = {
1521
      "tenant_id",
1522
      "hold",
1523
      "limit"
1524
    };
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);
1528
    }
1529
    for (int64_t i = 0; i < tenant_cnt && !gen.is_end(); ++i) {
1530
      auto tenant_id = tenant_ids[i];
1531
      gen.next_row();
1532
      // tenant_id
1533
      gen.next_column(tenant_id);
1534
      // hold
1535
      gen.next_column(ObMallocAllocator::get_instance()->get_tenant_hold(tenant_id));
1536
      // limit
1537
      gen.next_column(ObMallocAllocator::get_instance()->get_tenant_limit(tenant_id));
1538

1539
      gen.row_end();
1540
    }
1541
    diagnose::free(tenant_ids);
1542
  }
1543
  return 1;
1544
}
1545

1546
// list{list, list...} = select_mem_leak_checker_info()
1547
int select_mem_leak_checker_info(lua_State *L)
1548
{
1549
  int argc = lua_gettop(L);
1550
  ObMemLeakChecker* leak_checker = &get_mem_leak_checker();
1551
  if (argc > 1) {
1552
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_mem_leak_checker_info() failed, bad arguments count, should be less than 2.");
1553
    lua_pushnil(L);
1554
  } else if (OB_ISNULL(leak_checker)) {
1555
    OB_LOG_RET(ERROR, OB_ERR_UNEXPECTED, "leak checker is null");
1556
    lua_pushnil(L);
1557
  } else {
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));
1564
    } else {
1565
      std::vector<const char*> columns = {
1566
        "mod_name",
1567
        "mod_type",
1568
        "alloc_count",
1569
        "alloc_size",
1570
        "back_trace"
1571
      };
1572
      LuaVtableGenerator gen(L, columns);
1573
      for (auto it = info_map->begin(); it != info_map->end() && !gen.is_end(); ++it) {
1574
        gen.next_row();
1575
        // mod_name
1576
        gen.next_column(leak_checker->get_str());
1577
        // mod_type
1578
        gen.next_column("user");
1579
        // alloc_count
1580
        gen.next_column(it->second.first);
1581
        // alloc_size
1582
        gen.next_column(it->second.second);
1583
        // back_trace
1584
        gen.next_column(it->first.bt_);
1585

1586
        gen.row_end();
1587
      }
1588
    }
1589
  }
1590
  return 1;
1591
}
1592

1593
// list{list, list...} = select_compaction_diagnose_info()
1594
int select_compaction_diagnose_info(lua_State *L)
1595
{
1596
  int argc = lua_gettop(L);
1597
  if (argc > 1) {
1598
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_compaction_diagnose_info() failed, bad arguments count, should be less than 2.");
1599
    lua_pushnil(L);
1600
  } else {
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));
1606
      lua_pushnil(L);
1607
    } else {
1608
      std::vector<const char*> columns = {
1609
        "tenant_id",
1610
        "merge_type",
1611
        "ls_id",
1612
        "tablet_id",
1613
        "status",
1614
        "create_time",
1615
        "diagnose_info"
1616
      };
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()) {
1620
        gen.next_row();
1621
        // tenant_id
1622
        gen.next_column(diagnose_info.tenant_id_);
1623
        // merge_type
1624
        gen.next_column(merge_type_to_str(diagnose_info.merge_type_));
1625
        // ls_id
1626
        gen.next_column(diagnose_info.ls_id_);
1627
        // tablet_id
1628
        gen.next_column(diagnose_info.tablet_id_);
1629
        // status
1630
        gen.next_column(diagnose_info.get_diagnose_status_str(diagnose_info.status_));
1631
        // create_time
1632
        gen.next_column(diagnose_info.timestamp_);
1633
        // diagnose_info
1634
        gen.next_column(diagnose_info.diagnose_info_);
1635

1636
        gen.row_end();
1637
      }
1638
      if (OB_FAIL(ret) && OB_ITER_END != ret) {
1639
        OB_LOG(ERROR, "Fail to get next suggestion info", K(ret));
1640
      }
1641
    }
1642
  }
1643
  return 1;
1644
}
1645

1646
// list{list, list...} = select_server_schema_info()
1647
int select_server_schema_info(lua_State *L)
1648
{
1649
  int argc = lua_gettop(L);
1650
  if (argc > 1) {
1651
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_server_schema_info() failed, bad arguments count, should be less than 2.");
1652
    lua_pushnil(L);
1653
  } else {
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));
1661
      lua_pushnil(L);
1662
    } else if (OB_FAIL(guard.get_tenant_ids(tenant_ids))) {
1663
      OB_LOG(ERROR, "fail to get tenant_ids", K(ret));
1664
      lua_pushnil(L);
1665
    } else {
1666
      std::vector<const char*> columns = {
1667
        "tenant_id",
1668
        "refreshed_schema_version",
1669
        "received_schema_version",
1670
        "schema_count",
1671
        "schema_size",
1672
        "min_sstable_schema_version"
1673
      };
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));
1685
        } else {
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));
1693
          }
1694
          gen.next_row();
1695
          // 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);
1701
          // schema_count
1702
          gen.next_column(schema_count);
1703
          // schema_size
1704
          gen.next_column(schema_size);
1705
          // min_sstable_schema_version
1706
          gen.next_column(OB_INVALID_VERSION);
1707

1708
          gen.row_end();
1709
        }
1710
      }
1711
    }
1712
  }
1713
  return 1;
1714
}
1715

1716
// list{list, list...} = select_schema_slot()
1717
int select_schema_slot(lua_State *L)
1718
{
1719
  int argc = lua_gettop(L);
1720
  if (argc > 1) {
1721
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_schema_slot() failed, bad arguments count, should be less than 2.");
1722
    lua_pushnil(L);
1723
  } else {
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));
1730
      lua_pushnil(L);
1731
    } else {
1732
      std::vector<const char*> columns = {
1733
        "tenant_id",
1734
        "slot_id",
1735
        "schema_version",
1736
        "schema_count",
1737
        "total_ref_cnt",
1738
        "ref_info"
1739
      };
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));
1747
        } else {
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);
1750
            gen.next_row();
1751
            // tenant_id
1752
            gen.next_column(schema_slot.get_tenant_id());
1753
            // slot_id
1754
            gen.next_column(schema_slot.get_slot_id());
1755
            // schema_version
1756
            gen.next_column(schema_slot.get_schema_version());
1757
            // schema_count
1758
            gen.next_column(schema_slot.get_schema_count());
1759
            // total_ref_cnt
1760
            gen.next_column(schema_slot.get_ref_cnt());
1761
            // ref_info
1762
            if (OB_NOT_NULL(schema_slot.get_mod_ref_infos().ptr())) {
1763
              gen.next_column(schema_slot.get_mod_ref_infos());
1764
            } else {
1765
              gen.next_column("");
1766
            }
1767

1768
            gen.row_end();
1769
          }
1770
        }
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);
1775
          }
1776
          schema_slot_infos.at(slot_idx).reset();
1777
        }
1778
        schema_slot_infos.reset();
1779
      }
1780
    }
1781
  }
1782
  return 1;
1783
}
1784

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);
1788

1789
// list{list, list...} = dump_threads_info()
1790
int dump_thread_info(lua_State *L)
1791
{
1792
  int argc = lua_gettop(L);
1793
  if (argc > 1) {
1794
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call dump_thread_info() failed, bad arguments count, should be less than 2.");
1795
  } else {
1796
    std::vector<const char*> columns = {
1797
      "tname",
1798
      "tid",
1799
      "thread_base",
1800
      "loop_ts",
1801
      "latch_hold",
1802
      "latch_wait",
1803
      "trace_id",
1804
      "status",
1805
      "wait_event"
1806
    };
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
1814
        gen.next_row();
1815
        // tname
1816
        GET_OTHER_TSI_ADDR(tname, &(ob_get_tname()[0]));
1817
        // PAY ATTENTION HERE
1818
        gen.next_column(thread_base + tname_offset);
1819
        // tid
1820
        GET_OTHER_TSI_ADDR(tid, &get_tid_cache());
1821
        gen.next_column(tid);
1822
        // thread_base
1823
        {
1824
          char addr[32];
1825
          snprintf(addr, 32, "%p", thread_base);
1826
          gen.next_column(addr);
1827
        }
1828
        // loop_ts
1829
        GET_OTHER_TSI_ADDR(loop_ts, &oceanbase::lib::Thread::loop_ts_);
1830
        gen.next_column(loop_ts);
1831
        // latch_hold
1832
        {
1833
          char addrs[256];
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);
1838
          addrs[0] = 0;
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;
1843
              uint32_t val = 0;
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]);
1850
              }
1851
            }
1852
          }
1853
          if (0 == addrs[0]) {
1854
            gen.next_column("NULL");
1855
          } else {
1856
            gen.next_column(addrs);
1857
          }
1858
        }
1859
        // latch_wait
1860
        GET_OTHER_TSI_ADDR(wait_addr, &ObLatch::current_wait);
1861
        if (OB_NOT_NULL(wait_addr)) {
1862
          char addr[32];
1863
          snprintf(addr, 32, "%p", wait_addr);
1864
          gen.next_column(addr);
1865
        } else {
1866
          gen.next_column("NULL");
1867
        }
1868
        // trace_id
1869
        {
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);
1874
        }
1875
        // status
1876
        GET_OTHER_TSI_ADDR(blocking_ts, &Thread::blocking_ts_);
1877
        {
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";
1887
          } else {
1888
            status_str = "Run";
1889
          }
1890
          gen.next_column(status_str);
1891
        }
1892
        // wait_event
1893
        {
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];
1901
          ObAddr addr;
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)) {
1908
            uint32_t val = 0;
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);
1915
            } else {
1916
              IGNORE_RETURN snprintf(wait_event, BUF_LEN, "%u rdlocks", val & 0x3fffffff);
1917
            }
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_);
1921
            int64_t pos1 = 0;
1922
            int64_t pos2 = 0;
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);
1927
            }
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);
1940
          }
1941
          gen.next_column(wait_event);
1942
        }
1943
        gen.row_end();
1944
      }
1945
    }
1946
  }
1947
  return 1;
1948
}
1949

1950
// list{list, list...} = select_malloc_sample_info()
1951
int select_malloc_sample_info(lua_State *L)
1952
{
1953
  int ret = OB_SUCCESS;
1954
  int argc = lua_gettop(L);
1955
  ObMallocSampleMap malloc_sample_map;
1956
  if (argc > 1) {
1957
    OB_LOG_RET(ERROR, OB_INVALID_ARGUMENT, "call select_malloc_sample_info() failed, bad arguments count, should be less than 2.");
1958
    lua_pushnil(L);
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));
1963
  } else {
1964
    std::vector<const char*> columns = {
1965
      "tenant_id",
1966
      "ctx_id",
1967
      "mod_name",
1968
      "back_trace",
1969
      "ctx_name",
1970
      "alloc_count",
1971
      "alloc_bytes"
1972
    };
1973
    LuaVtableGenerator gen(L, columns);
1974
    for (auto it = malloc_sample_map.begin(); it != malloc_sample_map.end() && !gen.is_end(); ++it) {
1975
      gen.next_row();
1976
      // tenant_id
1977
      gen.next_column(it->first.tenant_id_);
1978
      // ctx_id
1979
      gen.next_column(it->first.ctx_id_);
1980
      // mod_name
1981
      gen.next_column(it->first.label_);
1982
      // back_trace
1983
      {
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);
1987
      }
1988
      // ctx_name
1989
      gen.next_column(get_global_ctx_info().get_ctx_name(it->first.ctx_id_));
1990
      // alloc_count
1991
      gen.next_column(it->second.alloc_count_);
1992
      // alloc_bytes
1993
      gen.next_column(it->second.alloc_bytes_);
1994

1995
      gen.row_end();
1996
    }
1997
  }
1998
  return 1;
1999
}
2000

2001
// int = set_system_tenant_limit_mode(int)
2002
int set_system_tenant_limit_mode(lua_State* L)
2003
{
2004
  int ret = OB_SUCCESS;
2005
  int argc = lua_gettop(L);
2006
  if (1 != argc) {
2007
    OB_LOG(ERROR, "call set_system_tenant_limit_mode() failed, bad arguments count, should be 1.");
2008
    ret = OB_INVALID_ARGUMENT;
2009
  } else {
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);
2014
#endif
2015
    lua_pushinteger(L, 1);
2016
  }
2017
  if (OB_FAIL(ret)) {
2018
    lua_pushinteger(L, -1);
2019
  }
2020
  return 1;
2021
}
2022

2023
// API end
2024

2025
int get_tenant_sysstat(int64_t tenant_id, int64_t statistic, int64_t &value)
2026
{
2027
  int ret = OB_SUCCESS;
2028
  ObArenaAllocator diag_allocator;
2029
  HEAP_VAR(ObDiagnoseTenantInfo, diag_info, &diag_allocator) {
2030
    if (statistic < 0
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))) {
2035
      // do nothing
2036
    } else if (OB_FAIL(observer::ObAllVirtualSysStat::update_all_stats(tenant_id, diag_info.get_set_stat_stats()))) {
2037
      // do nothing
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;
2042
      } else {
2043
        value = stat->stat_value_;
2044
      }
2045
    } else {
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;
2049
      } else {
2050
        value = stat->stat_value_;
2051
      }
2052
    }
2053
  }
2054
  return ret;
2055
}
2056

2057
int summary_each_eio_info(char *buf, int &pos, int buf_len, easy_io_t *eio, const char *rpc_des)
2058
{
2059
  int ret = OB_SUCCESS;
2060
  int io_th_count = 0;
2061
  easy_io_thread_t *ioth = NULL;
2062
  easy_connection_t *c = NULL;
2063
  int len = 0;
2064
  char output[512];
2065

2066
  if (OB_ISNULL(buf) || OB_ISNULL(eio) || OB_ISNULL(rpc_des)) {
2067
    ret = OB_SUCCESS;
2068
  } else if (pos >= buf_len) {
2069
    ret = OB_INVALID_ARGUMENT;
2070
  } else {
2071
      len = strlen(rpc_des);
2072
      if (pos + len > buf_len) {
2073
        ret = OB_INVALID_ARGUMENT;
2074
      } else {
2075
        strncpy(buf + pos, rpc_des, len);
2076
        pos += len;
2077
        io_th_count = eio->io_thread_count;
2078

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;
2088
          } else {
2089
            strncpy(buf + pos, output, len);
2090
            pos += 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;
2097
                break;
2098
              }
2099
              strncpy(buf + pos, output, len);
2100
              pos += len;
2101
            }
2102
          }
2103
        }
2104
      }
2105
    }
2106

2107
  return ret;
2108
}
2109

2110
void *diagnose::alloc(const int size)
2111
{
2112
  return get_global_allocator().alloc(size);
2113
}
2114

2115
void diagnose::free(void *ptr)
2116
{
2117
  if (OB_NOT_NULL(ptr)) {
2118
    get_global_allocator().free(ptr);
2119
  }
2120
}
2121

2122
void APIRegister::register_api(lua_State* L)
2123
{
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);
2152
}
2153

2154
int APIRegister::flush()
2155
{
2156
  int ret = OB_SUCCESS;
2157
  if (0 == print_offset_) {
2158
    // do nothing
2159
  } else if (conn_fd_ < 0) {
2160
    ret = OB_ERR_UNEXPECTED;
2161
  } else {
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));
2166
    }
2167
    print_offset_ = 0;
2168
    memset(print_buffer_, 0, print_capacity_);
2169
  }
2170
  return ret;
2171
}
2172

2173
int APIRegister::append(const char *buffer, const int len)
2174
{
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;
2183
  } else {
2184
    strncpy(print_buffer_ + print_offset_, buffer, len);
2185
    print_offset_ += len;
2186
  }
2187
  return ret;
2188
}
2189

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.