1/*
2 Copyright (c) 2012, Monty Program Ab
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17#include <my_global.h>
18
19/* C++ standard header files */
20#include <algorithm>
21#include <cctype>
22#include <map>
23#include <string>
24#include <vector>
25
26/* MySQL header files */
27#include <sql_show.h>
28
29/* RocksDB header files */
30#include "rocksdb/compaction_filter.h"
31#include "rocksdb/convenience.h"
32#include "rocksdb/filter_policy.h"
33#include "rocksdb/memtablerep.h"
34#include "rocksdb/merge_operator.h"
35#include "rocksdb/slice_transform.h"
36#include "rocksdb/utilities/transaction_db.h"
37
38/* MyRocks header files */
39#include "./ha_rocksdb.h"
40#include "./ha_rocksdb_proto.h"
41#include "./rdb_cf_manager.h"
42#include "./rdb_datadic.h"
43#include "./rdb_utils.h"
44#include "./rdb_mariadb_server_port.h"
45
46#include "./rdb_mariadb_port.h"
47
48namespace myrocks {
49
50/**
51 Define the INFORMATION_SCHEMA (I_S) structures needed by MyRocks storage
52 engine.
53*/
54
55#define ROCKSDB_FIELD_INFO(_name_, _len_, _type_, _flag_) \
56 { _name_, _len_, _type_, 0, _flag_, nullptr, 0 }
57
58#define ROCKSDB_FIELD_INFO_END \
59 ROCKSDB_FIELD_INFO(nullptr, 0, MYSQL_TYPE_NULL, 0)
60
61/*
62 Support for INFORMATION_SCHEMA.ROCKSDB_CFSTATS dynamic table
63 */
64namespace RDB_CFSTATS_FIELD {
65enum { CF_NAME = 0, STAT_TYPE, VALUE };
66} // namespace RDB_CFSTATS_FIELD
67
68static ST_FIELD_INFO rdb_i_s_cfstats_fields_info[] = {
69 ROCKSDB_FIELD_INFO("CF_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
70 ROCKSDB_FIELD_INFO("STAT_TYPE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
71 ROCKSDB_FIELD_INFO("VALUE", sizeof(uint64_t), MYSQL_TYPE_LONGLONG, 0),
72 ROCKSDB_FIELD_INFO_END};
73
74static int rdb_i_s_cfstats_fill_table(
75 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
76 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
77 DBUG_ENTER_FUNC();
78
79 DBUG_ASSERT(tables != nullptr);
80 DBUG_ASSERT(tables->table != nullptr);
81 DBUG_ASSERT(tables->table->field != nullptr);
82
83 int ret = 0;
84 uint64_t val;
85
86 const std::vector<std::pair<const std::string, std::string>> cf_properties = {
87 {rocksdb::DB::Properties::kNumImmutableMemTable,
88 "NUM_IMMUTABLE_MEM_TABLE"},
89 {rocksdb::DB::Properties::kMemTableFlushPending,
90 "MEM_TABLE_FLUSH_PENDING"},
91 {rocksdb::DB::Properties::kCompactionPending, "COMPACTION_PENDING"},
92 {rocksdb::DB::Properties::kCurSizeActiveMemTable,
93 "CUR_SIZE_ACTIVE_MEM_TABLE"},
94 {rocksdb::DB::Properties::kCurSizeAllMemTables,
95 "CUR_SIZE_ALL_MEM_TABLES"},
96 {rocksdb::DB::Properties::kNumEntriesActiveMemTable,
97 "NUM_ENTRIES_ACTIVE_MEM_TABLE"},
98 {rocksdb::DB::Properties::kNumEntriesImmMemTables,
99 "NUM_ENTRIES_IMM_MEM_TABLES"},
100 {rocksdb::DB::Properties::kEstimateTableReadersMem,
101 "NON_BLOCK_CACHE_SST_MEM_USAGE"},
102 {rocksdb::DB::Properties::kNumLiveVersions, "NUM_LIVE_VERSIONS"}};
103
104 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
105
106 if (!rdb) {
107 DBUG_RETURN(ret);
108 }
109
110 const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
111
112 for (const auto &cf_name : cf_manager.get_cf_names()) {
113 DBUG_ASSERT(!cf_name.empty());
114 rocksdb::ColumnFamilyHandle *cfh = cf_manager.get_cf(cf_name);
115 if (cfh == nullptr) {
116 continue;
117 }
118
119 for (const auto &property : cf_properties) {
120 if (!rdb->GetIntProperty(cfh, property.first, &val)) {
121 continue;
122 }
123
124 tables->table->field[RDB_CFSTATS_FIELD::CF_NAME]->store(
125 cf_name.c_str(), cf_name.size(), system_charset_info);
126 tables->table->field[RDB_CFSTATS_FIELD::STAT_TYPE]->store(
127 property.second.c_str(), property.second.size(), system_charset_info);
128 tables->table->field[RDB_CFSTATS_FIELD::VALUE]->store(val, true);
129
130 ret = static_cast<int>(
131 my_core::schema_table_store_record(thd, tables->table));
132
133 if (ret) {
134 DBUG_RETURN(ret);
135 }
136 }
137 }
138
139 DBUG_RETURN(0);
140}
141
142static int rdb_i_s_cfstats_init(void *p) {
143 DBUG_ENTER_FUNC();
144
145 if (prevent_myrocks_loading)
146 DBUG_RETURN(1);
147
148 DBUG_ASSERT(p != nullptr);
149
150 my_core::ST_SCHEMA_TABLE *schema;
151
152 schema = (my_core::ST_SCHEMA_TABLE *)p;
153
154 schema->fields_info = rdb_i_s_cfstats_fields_info;
155 schema->fill_table = rdb_i_s_cfstats_fill_table;
156
157 DBUG_RETURN(0);
158}
159
160/*
161 Support for INFORMATION_SCHEMA.ROCKSDB_DBSTATS dynamic table
162 */
163namespace RDB_DBSTATS_FIELD {
164enum { STAT_TYPE = 0, VALUE };
165} // namespace RDB_DBSTATS_FIELD
166
167static ST_FIELD_INFO rdb_i_s_dbstats_fields_info[] = {
168 ROCKSDB_FIELD_INFO("STAT_TYPE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
169 ROCKSDB_FIELD_INFO("VALUE", sizeof(uint64_t), MYSQL_TYPE_LONGLONG, 0),
170 ROCKSDB_FIELD_INFO_END};
171
172static int rdb_i_s_dbstats_fill_table(
173 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
174 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
175 DBUG_ENTER_FUNC();
176
177 DBUG_ASSERT(tables != nullptr);
178 DBUG_ASSERT(tables->table != nullptr);
179 DBUG_ASSERT(tables->table->field != nullptr);
180
181 int ret = 0;
182 uint64_t val;
183
184 const std::vector<std::pair<std::string, std::string>> db_properties = {
185 {rocksdb::DB::Properties::kBackgroundErrors, "DB_BACKGROUND_ERRORS"},
186 {rocksdb::DB::Properties::kNumSnapshots, "DB_NUM_SNAPSHOTS"},
187 {rocksdb::DB::Properties::kOldestSnapshotTime,
188 "DB_OLDEST_SNAPSHOT_TIME"}};
189
190 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
191
192 if (!rdb) {
193 DBUG_RETURN(ret);
194 }
195
196 const rocksdb::BlockBasedTableOptions &table_options =
197 rdb_get_table_options();
198
199 for (const auto &property : db_properties) {
200 if (!rdb->GetIntProperty(property.first, &val)) {
201 continue;
202 }
203
204 tables->table->field[RDB_DBSTATS_FIELD::STAT_TYPE]->store(
205 property.second.c_str(), property.second.size(), system_charset_info);
206 tables->table->field[RDB_DBSTATS_FIELD::VALUE]->store(val, true);
207
208 ret = static_cast<int>(
209 my_core::schema_table_store_record(thd, tables->table));
210
211 if (ret) {
212 DBUG_RETURN(ret);
213 }
214 }
215
216 /*
217 Currently, this can only show the usage of a block cache allocated
218 directly by the handlerton. If the column family config specifies a block
219 cache (i.e. the column family option has a parameter such as
220 block_based_table_factory={block_cache=1G}), then the block cache is
221 allocated within the rocksdb::GetColumnFamilyOptionsFromString().
222
223 There is no interface to retrieve this block cache, nor fetch the usage
224 information from the column family.
225 */
226 val = (table_options.block_cache ? table_options.block_cache->GetUsage() : 0);
227
228 tables->table->field[RDB_DBSTATS_FIELD::STAT_TYPE]->store(
229 STRING_WITH_LEN("DB_BLOCK_CACHE_USAGE"), system_charset_info);
230 tables->table->field[RDB_DBSTATS_FIELD::VALUE]->store(val, true);
231
232 ret =
233 static_cast<int>(my_core::schema_table_store_record(thd, tables->table));
234
235 DBUG_RETURN(ret);
236}
237
238static int rdb_i_s_dbstats_init(void *const p) {
239 DBUG_ENTER_FUNC();
240
241 if (prevent_myrocks_loading)
242 DBUG_RETURN(1);
243
244 DBUG_ASSERT(p != nullptr);
245
246 my_core::ST_SCHEMA_TABLE *schema;
247
248 schema = (my_core::ST_SCHEMA_TABLE *)p;
249
250 schema->fields_info = rdb_i_s_dbstats_fields_info;
251 schema->fill_table = rdb_i_s_dbstats_fill_table;
252
253 DBUG_RETURN(0);
254}
255
256/*
257 Support for INFORMATION_SCHEMA.ROCKSDB_PERF_CONTEXT dynamic table
258 */
259namespace RDB_PERF_CONTEXT_FIELD {
260enum { TABLE_SCHEMA = 0, TABLE_NAME, PARTITION_NAME, STAT_TYPE, VALUE };
261} // namespace RDB_PERF_CONTEXT_FIELD
262
263static ST_FIELD_INFO rdb_i_s_perf_context_fields_info[] = {
264 ROCKSDB_FIELD_INFO("TABLE_SCHEMA", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
265 ROCKSDB_FIELD_INFO("TABLE_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
266 ROCKSDB_FIELD_INFO("PARTITION_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING,
267 MY_I_S_MAYBE_NULL),
268 ROCKSDB_FIELD_INFO("STAT_TYPE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
269 ROCKSDB_FIELD_INFO("VALUE", sizeof(uint64_t), MYSQL_TYPE_LONGLONG, 0),
270 ROCKSDB_FIELD_INFO_END};
271
272static int rdb_i_s_perf_context_fill_table(
273 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
274 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
275 DBUG_ENTER_FUNC();
276
277 DBUG_ASSERT(thd != nullptr);
278 DBUG_ASSERT(tables != nullptr);
279 DBUG_ASSERT(tables->table != nullptr);
280
281 int ret = 0;
282 Field **field = tables->table->field;
283 DBUG_ASSERT(field != nullptr);
284
285 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
286
287 if (!rdb) {
288 DBUG_RETURN(ret);
289 }
290
291 const std::vector<std::string> tablenames = rdb_get_open_table_names();
292
293 for (const auto &it : tablenames) {
294 std::string str, dbname, tablename, partname;
295 Rdb_perf_counters counters;
296
297 int rc = rdb_normalize_tablename(it, &str);
298
299 if (rc != HA_EXIT_SUCCESS) {
300 DBUG_RETURN(rc);
301 }
302
303 if (rdb_split_normalized_tablename(str, &dbname, &tablename, &partname)) {
304 continue;
305 }
306
307 if (rdb_get_table_perf_counters(it.c_str(), &counters)) {
308 continue;
309 }
310
311 field[RDB_PERF_CONTEXT_FIELD::TABLE_SCHEMA]->store(
312 dbname.c_str(), dbname.size(), system_charset_info);
313 field[RDB_PERF_CONTEXT_FIELD::TABLE_NAME]->store(
314 tablename.c_str(), tablename.size(), system_charset_info);
315
316 if (partname.size() == 0) {
317 field[RDB_PERF_CONTEXT_FIELD::PARTITION_NAME]->set_null();
318 } else {
319 field[RDB_PERF_CONTEXT_FIELD::PARTITION_NAME]->set_notnull();
320 field[RDB_PERF_CONTEXT_FIELD::PARTITION_NAME]->store(
321 partname.c_str(), partname.size(), system_charset_info);
322 }
323
324 for (int i = 0; i < PC_MAX_IDX; i++) {
325 field[RDB_PERF_CONTEXT_FIELD::STAT_TYPE]->store(
326 rdb_pc_stat_types[i].c_str(), rdb_pc_stat_types[i].size(),
327 system_charset_info);
328 field[RDB_PERF_CONTEXT_FIELD::VALUE]->store(counters.m_value[i], true);
329
330 ret = static_cast<int>(
331 my_core::schema_table_store_record(thd, tables->table));
332
333 if (ret) {
334 DBUG_RETURN(ret);
335 }
336 }
337 }
338
339 DBUG_RETURN(0);
340}
341
342static int rdb_i_s_perf_context_init(void *const p) {
343 DBUG_ENTER_FUNC();
344
345 if (prevent_myrocks_loading)
346 DBUG_RETURN(1);
347 DBUG_ASSERT(p != nullptr);
348
349 my_core::ST_SCHEMA_TABLE *schema;
350
351 schema = (my_core::ST_SCHEMA_TABLE *)p;
352
353 schema->fields_info = rdb_i_s_perf_context_fields_info;
354 schema->fill_table = rdb_i_s_perf_context_fill_table;
355
356 DBUG_RETURN(0);
357}
358
359/*
360 Support for INFORMATION_SCHEMA.ROCKSDB_PERF_CONTEXT_GLOBAL dynamic table
361 */
362namespace RDB_PERF_CONTEXT_GLOBAL_FIELD {
363enum { STAT_TYPE = 0, VALUE };
364} // namespace RDB_PERF_CONTEXT_GLOBAL_FIELD
365
366static ST_FIELD_INFO rdb_i_s_perf_context_global_fields_info[] = {
367 ROCKSDB_FIELD_INFO("STAT_TYPE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
368 ROCKSDB_FIELD_INFO("VALUE", sizeof(uint64_t), MYSQL_TYPE_LONGLONG, 0),
369 ROCKSDB_FIELD_INFO_END};
370
371static int rdb_i_s_perf_context_global_fill_table(
372 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
373 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
374 DBUG_ENTER_FUNC();
375
376 DBUG_ASSERT(thd != nullptr);
377 DBUG_ASSERT(tables != nullptr);
378 DBUG_ASSERT(tables->table != nullptr);
379 DBUG_ASSERT(tables->table->field != nullptr);
380
381 int ret = 0;
382
383 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
384
385 if (!rdb) {
386 DBUG_RETURN(ret);
387 }
388
389 // Get a copy of the global perf counters.
390 Rdb_perf_counters global_counters;
391 rdb_get_global_perf_counters(&global_counters);
392
393 for (int i = 0; i < PC_MAX_IDX; i++) {
394 tables->table->field[RDB_PERF_CONTEXT_GLOBAL_FIELD::STAT_TYPE]->store(
395 rdb_pc_stat_types[i].c_str(), rdb_pc_stat_types[i].size(),
396 system_charset_info);
397 tables->table->field[RDB_PERF_CONTEXT_GLOBAL_FIELD::VALUE]->store(
398 global_counters.m_value[i], true);
399
400 ret = static_cast<int>(
401 my_core::schema_table_store_record(thd, tables->table));
402
403 if (ret) {
404 DBUG_RETURN(ret);
405 }
406 }
407
408 DBUG_RETURN(0);
409}
410
411static int rdb_i_s_perf_context_global_init(void *const p) {
412 DBUG_ENTER_FUNC();
413
414 if (prevent_myrocks_loading)
415 DBUG_RETURN(1);
416
417 DBUG_ASSERT(p != nullptr);
418
419 my_core::ST_SCHEMA_TABLE *schema;
420
421 schema = (my_core::ST_SCHEMA_TABLE *)p;
422
423 schema->fields_info = rdb_i_s_perf_context_global_fields_info;
424 schema->fill_table = rdb_i_s_perf_context_global_fill_table;
425
426 DBUG_RETURN(0);
427}
428
429/*
430 Support for INFORMATION_SCHEMA.ROCKSDB_CFOPTIONS dynamic table
431 */
432namespace RDB_CFOPTIONS_FIELD {
433enum { CF_NAME = 0, OPTION_TYPE, VALUE };
434} // namespace RDB_CFOPTIONS_FIELD
435
436static ST_FIELD_INFO rdb_i_s_cfoptions_fields_info[] = {
437 ROCKSDB_FIELD_INFO("CF_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
438 ROCKSDB_FIELD_INFO("OPTION_TYPE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
439 ROCKSDB_FIELD_INFO("VALUE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
440 ROCKSDB_FIELD_INFO_END};
441
442static int rdb_i_s_cfoptions_fill_table(
443 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
444 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
445 DBUG_ENTER_FUNC();
446
447 DBUG_ASSERT(thd != nullptr);
448 DBUG_ASSERT(tables != nullptr);
449
450 int ret = 0;
451
452 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
453
454 if (!rdb) {
455 DBUG_RETURN(ret);
456 }
457
458 Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
459
460 for (const auto &cf_name : cf_manager.get_cf_names()) {
461 std::string val;
462 rocksdb::ColumnFamilyOptions opts;
463
464 DBUG_ASSERT(!cf_name.empty());
465 cf_manager.get_cf_options(cf_name, &opts);
466
467 std::vector<std::pair<std::string, std::string>> cf_option_types = {
468 {"COMPARATOR", opts.comparator == nullptr
469 ? "NULL"
470 : std::string(opts.comparator->Name())},
471 {"MERGE_OPERATOR", opts.merge_operator == nullptr
472 ? "NULL"
473 : std::string(opts.merge_operator->Name())},
474 {"COMPACTION_FILTER",
475 opts.compaction_filter == nullptr
476 ? "NULL"
477 : std::string(opts.compaction_filter->Name())},
478 {"COMPACTION_FILTER_FACTORY",
479 opts.compaction_filter_factory == nullptr
480 ? "NULL"
481 : std::string(opts.compaction_filter_factory->Name())},
482 {"WRITE_BUFFER_SIZE", std::to_string(opts.write_buffer_size)},
483 {"MAX_WRITE_BUFFER_NUMBER",
484 std::to_string(opts.max_write_buffer_number)},
485 {"MIN_WRITE_BUFFER_NUMBER_TO_MERGE",
486 std::to_string(opts.min_write_buffer_number_to_merge)},
487 {"NUM_LEVELS", std::to_string(opts.num_levels)},
488 {"LEVEL0_FILE_NUM_COMPACTION_TRIGGER",
489 std::to_string(opts.level0_file_num_compaction_trigger)},
490 {"LEVEL0_SLOWDOWN_WRITES_TRIGGER",
491 std::to_string(opts.level0_slowdown_writes_trigger)},
492 {"LEVEL0_STOP_WRITES_TRIGGER",
493 std::to_string(opts.level0_stop_writes_trigger)},
494 {"MAX_MEM_COMPACTION_LEVEL",
495 std::to_string(opts.max_mem_compaction_level)},
496 {"TARGET_FILE_SIZE_BASE", std::to_string(opts.target_file_size_base)},
497 {"TARGET_FILE_SIZE_MULTIPLIER",
498 std::to_string(opts.target_file_size_multiplier)},
499 {"MAX_BYTES_FOR_LEVEL_BASE",
500 std::to_string(opts.max_bytes_for_level_base)},
501 {"LEVEL_COMPACTION_DYNAMIC_LEVEL_BYTES",
502 opts.level_compaction_dynamic_level_bytes ? "ON" : "OFF"},
503 {"MAX_BYTES_FOR_LEVEL_MULTIPLIER",
504 std::to_string(opts.max_bytes_for_level_multiplier)},
505 {"SOFT_RATE_LIMIT", std::to_string(opts.soft_rate_limit)},
506 {"HARD_RATE_LIMIT", std::to_string(opts.hard_rate_limit)},
507 {"RATE_LIMIT_DELAY_MAX_MILLISECONDS",
508 std::to_string(opts.rate_limit_delay_max_milliseconds)},
509 {"ARENA_BLOCK_SIZE", std::to_string(opts.arena_block_size)},
510 {"DISABLE_AUTO_COMPACTIONS",
511 opts.disable_auto_compactions ? "ON" : "OFF"},
512 {"PURGE_REDUNDANT_KVS_WHILE_FLUSH",
513 opts.purge_redundant_kvs_while_flush ? "ON" : "OFF"},
514 {"MAX_SEQUENTIAL_SKIP_IN_ITERATIONS",
515 std::to_string(opts.max_sequential_skip_in_iterations)},
516 {"MEMTABLE_FACTORY", opts.memtable_factory == nullptr
517 ? "NULL"
518 : opts.memtable_factory->Name()},
519 {"INPLACE_UPDATE_SUPPORT", opts.inplace_update_support ? "ON" : "OFF"},
520 {"INPLACE_UPDATE_NUM_LOCKS",
521 opts.inplace_update_num_locks ? "ON" : "OFF"},
522 {"MEMTABLE_PREFIX_BLOOM_BITS_RATIO",
523 std::to_string(opts.memtable_prefix_bloom_size_ratio)},
524 {"MEMTABLE_PREFIX_BLOOM_HUGE_PAGE_TLB_SIZE",
525 std::to_string(opts.memtable_huge_page_size)},
526 {"BLOOM_LOCALITY", std::to_string(opts.bloom_locality)},
527 {"MAX_SUCCESSIVE_MERGES", std::to_string(opts.max_successive_merges)},
528 {"OPTIMIZE_FILTERS_FOR_HITS",
529 (opts.optimize_filters_for_hits ? "ON" : "OFF")},
530 };
531
532 // get MAX_BYTES_FOR_LEVEL_MULTIPLIER_ADDITIONAL option value
533 val = opts.max_bytes_for_level_multiplier_additional.empty() ? "NULL" : "";
534
535 for (const auto &level : opts.max_bytes_for_level_multiplier_additional) {
536 val.append(std::to_string(level) + ":");
537 }
538
539 val.pop_back();
540 cf_option_types.push_back(
541 {"MAX_BYTES_FOR_LEVEL_MULTIPLIER_ADDITIONAL", val});
542
543 // get COMPRESSION_TYPE option value
544 GetStringFromCompressionType(&val, opts.compression);
545
546 if (val.empty()) {
547 val = "NULL";
548 }
549
550 cf_option_types.push_back({"COMPRESSION_TYPE", val});
551
552 // get COMPRESSION_PER_LEVEL option value
553 val = opts.compression_per_level.empty() ? "NULL" : "";
554
555 for (const auto &compression_type : opts.compression_per_level) {
556 std::string res;
557
558 GetStringFromCompressionType(&res, compression_type);
559
560 if (!res.empty()) {
561 val.append(res + ":");
562 }
563 }
564
565 val.pop_back();
566 cf_option_types.push_back({"COMPRESSION_PER_LEVEL", val});
567
568 // get compression_opts value
569 val = std::to_string(opts.compression_opts.window_bits) + ":";
570 val.append(std::to_string(opts.compression_opts.level) + ":");
571 val.append(std::to_string(opts.compression_opts.strategy));
572
573 cf_option_types.push_back({"COMPRESSION_OPTS", val});
574
575 // bottommost_compression
576 if (opts.bottommost_compression) {
577 std::string res;
578
579 GetStringFromCompressionType(&res, opts.bottommost_compression);
580
581 if (!res.empty()) {
582 cf_option_types.push_back({"BOTTOMMOST_COMPRESSION", res});
583 }
584 }
585
586 // get PREFIX_EXTRACTOR option
587 cf_option_types.push_back(
588 {"PREFIX_EXTRACTOR", opts.prefix_extractor == nullptr
589 ? "NULL"
590 : std::string(opts.prefix_extractor->Name())});
591
592 // get COMPACTION_STYLE option
593 switch (opts.compaction_style) {
594 case rocksdb::kCompactionStyleLevel:
595 val = "kCompactionStyleLevel";
596 break;
597 case rocksdb::kCompactionStyleUniversal:
598 val = "kCompactionStyleUniversal";
599 break;
600 case rocksdb::kCompactionStyleFIFO:
601 val = "kCompactionStyleFIFO";
602 break;
603 case rocksdb::kCompactionStyleNone:
604 val = "kCompactionStyleNone";
605 break;
606 default:
607 val = "NULL";
608 }
609
610 cf_option_types.push_back({"COMPACTION_STYLE", val});
611
612 // get COMPACTION_OPTIONS_UNIVERSAL related options
613 const rocksdb::CompactionOptionsUniversal compac_opts =
614 opts.compaction_options_universal;
615
616 val = "{SIZE_RATIO=";
617
618 val.append(std::to_string(compac_opts.size_ratio));
619 val.append("; MIN_MERGE_WIDTH=");
620 val.append(std::to_string(compac_opts.min_merge_width));
621 val.append("; MAX_MERGE_WIDTH=");
622 val.append(std::to_string(compac_opts.max_merge_width));
623 val.append("; MAX_SIZE_AMPLIFICATION_PERCENT=");
624 val.append(std::to_string(compac_opts.max_size_amplification_percent));
625 val.append("; COMPRESSION_SIZE_PERCENT=");
626 val.append(std::to_string(compac_opts.compression_size_percent));
627 val.append("; STOP_STYLE=");
628
629 switch (compac_opts.stop_style) {
630 case rocksdb::kCompactionStopStyleSimilarSize:
631 val.append("kCompactionStopStyleSimilarSize}");
632 break;
633 case rocksdb::kCompactionStopStyleTotalSize:
634 val.append("kCompactionStopStyleTotalSize}");
635 break;
636 default:
637 val.append("}");
638 }
639
640 cf_option_types.push_back({"COMPACTION_OPTIONS_UNIVERSAL", val});
641
642 // get COMPACTION_OPTION_FIFO option
643 cf_option_types.push_back(
644 {"COMPACTION_OPTION_FIFO::MAX_TABLE_FILES_SIZE",
645 std::to_string(opts.compaction_options_fifo.max_table_files_size)});
646
647 // get table related options
648 std::vector<std::string> table_options =
649 split_into_vector(opts.table_factory->GetPrintableTableOptions(), '\n');
650
651 for (auto option : table_options) {
652 option.erase(std::remove(option.begin(), option.end(), ' '),
653 option.end());
654
655 int pos = option.find(":");
656 std::string option_name = option.substr(0, pos);
657 std::string option_value = option.substr(pos + 1, option.length());
658 std::transform(option_name.begin(), option_name.end(),
659 option_name.begin(),
660 [](unsigned char c) { return std::toupper(c); });
661
662 cf_option_types.push_back(
663 {"TABLE_FACTORY::" + option_name, option_value});
664 }
665
666 for (const auto &cf_option_type : cf_option_types) {
667 DBUG_ASSERT(tables->table != nullptr);
668 DBUG_ASSERT(tables->table->field != nullptr);
669
670 tables->table->field[RDB_CFOPTIONS_FIELD::CF_NAME]->store(
671 cf_name.c_str(), cf_name.size(), system_charset_info);
672 tables->table->field[RDB_CFOPTIONS_FIELD::OPTION_TYPE]->store(
673 cf_option_type.first.c_str(), cf_option_type.first.size(),
674 system_charset_info);
675 tables->table->field[RDB_CFOPTIONS_FIELD::VALUE]->store(
676 cf_option_type.second.c_str(), cf_option_type.second.size(),
677 system_charset_info);
678
679 ret = static_cast<int>(
680 my_core::schema_table_store_record(thd, tables->table));
681
682 if (ret) {
683 DBUG_RETURN(ret);
684 }
685 }
686 }
687
688 DBUG_RETURN(0);
689}
690
691/*
692 Support for INFORMATION_SCHEMA.ROCKSDB_GLOBAL_INFO dynamic table
693 */
694namespace RDB_GLOBAL_INFO_FIELD {
695enum { TYPE = 0, NAME, VALUE };
696}
697
698static ST_FIELD_INFO rdb_i_s_global_info_fields_info[] = {
699 ROCKSDB_FIELD_INFO("TYPE", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
700 ROCKSDB_FIELD_INFO("NAME", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
701 ROCKSDB_FIELD_INFO("VALUE", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
702 ROCKSDB_FIELD_INFO_END};
703
704/*
705 * helper function for rdb_i_s_global_info_fill_table
706 * to insert (TYPE, KEY, VALUE) rows into
707 * information_schema.rocksdb_global_info
708 */
709static int rdb_global_info_fill_row(my_core::THD *const thd,
710 my_core::TABLE_LIST *const tables,
711 const char *const type,
712 const char *const name,
713 const char *const value) {
714 DBUG_ASSERT(thd != nullptr);
715 DBUG_ASSERT(tables != nullptr);
716 DBUG_ASSERT(tables->table != nullptr);
717 DBUG_ASSERT(type != nullptr);
718 DBUG_ASSERT(name != nullptr);
719 DBUG_ASSERT(value != nullptr);
720
721 Field **field = tables->table->field;
722 DBUG_ASSERT(field != nullptr);
723
724 field[RDB_GLOBAL_INFO_FIELD::TYPE]->store(type, strlen(type),
725 system_charset_info);
726 field[RDB_GLOBAL_INFO_FIELD::NAME]->store(name, strlen(name),
727 system_charset_info);
728 field[RDB_GLOBAL_INFO_FIELD::VALUE]->store(value, strlen(value),
729 system_charset_info);
730
731 return my_core::schema_table_store_record(thd, tables->table);
732}
733
734static int rdb_i_s_global_info_fill_table(
735 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
736 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
737 DBUG_ENTER_FUNC();
738
739 DBUG_ASSERT(thd != nullptr);
740 DBUG_ASSERT(tables != nullptr);
741
742 static const uint32_t INT_BUF_LEN = 21;
743 static const uint32_t CF_ID_INDEX_BUF_LEN = 60;
744
745 int ret = 0;
746
747 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
748
749 if (!rdb) {
750 DBUG_RETURN(ret);
751 }
752
753 /* binlog info */
754 Rdb_binlog_manager *const blm = rdb_get_binlog_manager();
755 DBUG_ASSERT(blm != nullptr);
756
757 char file_buf[FN_REFLEN + 1] = {0};
758 my_off_t pos = 0;
759 char pos_buf[INT_BUF_LEN] = {0};
760 char gtid_buf[GTID_BUF_LEN] = {0};
761
762 if (blm->read(file_buf, &pos, gtid_buf)) {
763 snprintf(pos_buf, INT_BUF_LEN, "%llu", (ulonglong)pos);
764
765 ret |= rdb_global_info_fill_row(thd, tables, "BINLOG", "FILE", file_buf);
766 ret |= rdb_global_info_fill_row(thd, tables, "BINLOG", "POS", pos_buf);
767 ret |= rdb_global_info_fill_row(thd, tables, "BINLOG", "GTID", gtid_buf);
768 }
769
770 /* max index info */
771 const Rdb_dict_manager *const dict_manager = rdb_get_dict_manager();
772 DBUG_ASSERT(dict_manager != nullptr);
773
774 uint32_t max_index_id;
775 char max_index_id_buf[INT_BUF_LEN] = {0};
776
777 if (dict_manager->get_max_index_id(&max_index_id)) {
778 snprintf(max_index_id_buf, INT_BUF_LEN, "%u", max_index_id);
779
780 ret |= rdb_global_info_fill_row(thd, tables, "MAX_INDEX_ID", "MAX_INDEX_ID",
781 max_index_id_buf);
782 }
783
784 /* cf_id -> cf_flags */
785 char cf_id_buf[INT_BUF_LEN] = {0};
786 char cf_value_buf[FN_REFLEN + 1] = {0};
787 const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
788
789 for (const auto &cf_handle : cf_manager.get_all_cf()) {
790 DBUG_ASSERT(cf_handle != nullptr);
791
792 uint flags;
793
794 if (!dict_manager->get_cf_flags(cf_handle->GetID(), &flags)) {
795 // NO_LINT_DEBUG
796 sql_print_error("RocksDB: Failed to get column family flags "
797 "from CF with id = %u. MyRocks data dictionary may "
798 "be corrupted.",
799 cf_handle->GetID());
800 abort();
801 }
802
803 snprintf(cf_id_buf, INT_BUF_LEN, "%u", cf_handle->GetID());
804 snprintf(cf_value_buf, FN_REFLEN, "%s [%u]", cf_handle->GetName().c_str(),
805 flags);
806
807 ret |= rdb_global_info_fill_row(thd, tables, "CF_FLAGS", cf_id_buf,
808 cf_value_buf);
809
810 if (ret) {
811 break;
812 }
813 }
814
815 /* DDL_DROP_INDEX_ONGOING */
816 std::unordered_set<GL_INDEX_ID> gl_index_ids;
817 dict_manager->get_ongoing_index_operation(
818 &gl_index_ids, Rdb_key_def::DDL_DROP_INDEX_ONGOING);
819 char cf_id_index_buf[CF_ID_INDEX_BUF_LEN] = {0};
820
821 for (auto gl_index_id : gl_index_ids) {
822 snprintf(cf_id_index_buf, CF_ID_INDEX_BUF_LEN, "cf_id:%u,index_id:%u",
823 gl_index_id.cf_id, gl_index_id.index_id);
824
825 ret |= rdb_global_info_fill_row(thd, tables, "DDL_DROP_INDEX_ONGOING",
826 cf_id_index_buf, "");
827
828 if (ret) {
829 break;
830 }
831 }
832
833 DBUG_RETURN(ret);
834}
835
836/*
837 Support for INFORMATION_SCHEMA.ROCKSDB_COMPACTION_STATS dynamic table
838 */
839static int rdb_i_s_compact_stats_fill_table(
840 my_core::THD *thd, my_core::TABLE_LIST *tables,
841 my_core::Item *cond MY_ATTRIBUTE((__unused__))) {
842 DBUG_ASSERT(thd != nullptr);
843 DBUG_ASSERT(tables != nullptr);
844
845 DBUG_ENTER_FUNC();
846
847 int ret = 0;
848 rocksdb::DB *rdb = rdb_get_rocksdb_db();
849
850 if (!rdb) {
851 DBUG_RETURN(ret);
852 }
853
854 Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
855
856 for (auto cf_name : cf_manager.get_cf_names()) {
857 rocksdb::ColumnFamilyHandle *cfh = cf_manager.get_cf(cf_name);
858
859 if (cfh == nullptr) {
860 continue;
861 }
862
863 std::map<std::string, std::string> props;
864 bool bool_ret MY_ATTRIBUTE((__unused__));
865 bool_ret = rdb->GetMapProperty(cfh, "rocksdb.cfstats", &props);
866 DBUG_ASSERT(bool_ret);
867
868 const std::string prop_name_prefix = "compaction.";
869 for (auto const &prop_ent : props) {
870 std::string prop_name = prop_ent.first;
871 if (prop_name.find(prop_name_prefix) != 0) {
872 continue;
873 }
874 std::string value = prop_ent.second;
875 std::size_t del_pos = prop_name.find('.', prop_name_prefix.size());
876 DBUG_ASSERT(del_pos != std::string::npos);
877 std::string level_str = prop_name.substr(
878 prop_name_prefix.size(), del_pos - prop_name_prefix.size());
879 std::string type_str = prop_name.substr(del_pos + 1);
880
881 Field **field = tables->table->field;
882 DBUG_ASSERT(field != nullptr);
883
884 field[0]->store(cf_name.c_str(), cf_name.size(), system_charset_info);
885 field[1]->store(level_str.c_str(), level_str.size(), system_charset_info);
886 field[2]->store(type_str.c_str(), type_str.size(), system_charset_info);
887 field[3]->store(std::stod(value));
888
889 ret |= static_cast<int>(
890 my_core::schema_table_store_record(thd, tables->table));
891
892 if (ret != 0) {
893 DBUG_RETURN(ret);
894 }
895 }
896 }
897
898 DBUG_RETURN(ret);
899}
900
901static ST_FIELD_INFO rdb_i_s_compact_stats_fields_info[] = {
902 ROCKSDB_FIELD_INFO("CF_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
903 ROCKSDB_FIELD_INFO("LEVEL", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
904 ROCKSDB_FIELD_INFO("TYPE", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
905 ROCKSDB_FIELD_INFO("VALUE", sizeof(double), MYSQL_TYPE_DOUBLE, 0),
906 ROCKSDB_FIELD_INFO_END};
907
908namespace // anonymous namespace = not visible outside this source file
909{
910struct Rdb_ddl_scanner : public Rdb_tables_scanner {
911 my_core::THD *m_thd;
912 my_core::TABLE *m_table;
913
914 int add_table(Rdb_tbl_def *tdef) override;
915};
916} // anonymous namespace
917
918/*
919 Support for INFORMATION_SCHEMA.ROCKSDB_DDL dynamic table
920 */
921namespace RDB_DDL_FIELD {
922enum {
923 TABLE_SCHEMA = 0,
924 TABLE_NAME,
925 PARTITION_NAME,
926 INDEX_NAME,
927 COLUMN_FAMILY,
928 INDEX_NUMBER,
929 INDEX_TYPE,
930 KV_FORMAT_VERSION,
931 TTL_DURATION,
932 INDEX_FLAGS,
933 CF,
934 AUTO_INCREMENT
935};
936} // namespace RDB_DDL_FIELD
937
938static ST_FIELD_INFO rdb_i_s_ddl_fields_info[] = {
939 ROCKSDB_FIELD_INFO("TABLE_SCHEMA", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
940 ROCKSDB_FIELD_INFO("TABLE_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
941 ROCKSDB_FIELD_INFO("PARTITION_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING,
942 MY_I_S_MAYBE_NULL),
943 ROCKSDB_FIELD_INFO("INDEX_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
944 ROCKSDB_FIELD_INFO("COLUMN_FAMILY", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
945 ROCKSDB_FIELD_INFO("INDEX_NUMBER", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
946 ROCKSDB_FIELD_INFO("INDEX_TYPE", sizeof(uint16_t), MYSQL_TYPE_SHORT, 0),
947 ROCKSDB_FIELD_INFO("KV_FORMAT_VERSION", sizeof(uint16_t), MYSQL_TYPE_SHORT,
948 0),
949 ROCKSDB_FIELD_INFO("TTL_DURATION", sizeof(uint64), MYSQL_TYPE_LONGLONG, 0),
950 ROCKSDB_FIELD_INFO("INDEX_FLAGS", sizeof(uint64), MYSQL_TYPE_LONGLONG, 0),
951 ROCKSDB_FIELD_INFO("CF", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
952 ROCKSDB_FIELD_INFO("AUTO_INCREMENT", sizeof(uint64_t), MYSQL_TYPE_LONGLONG,
953 MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED),
954 ROCKSDB_FIELD_INFO_END};
955
956int Rdb_ddl_scanner::add_table(Rdb_tbl_def *tdef) {
957 DBUG_ASSERT(tdef != nullptr);
958
959 int ret = 0;
960
961 DBUG_ASSERT(m_table != nullptr);
962 Field **field = m_table->field;
963 DBUG_ASSERT(field != nullptr);
964 const Rdb_dict_manager *dict_manager = rdb_get_dict_manager();
965
966 const std::string &dbname = tdef->base_dbname();
967 field[RDB_DDL_FIELD::TABLE_SCHEMA]->store(dbname.c_str(), dbname.size(),
968 system_charset_info);
969
970 const std::string &tablename = tdef->base_tablename();
971 field[RDB_DDL_FIELD::TABLE_NAME]->store(tablename.c_str(), tablename.size(),
972 system_charset_info);
973
974 const std::string &partname = tdef->base_partition();
975 if (partname.length() == 0) {
976 field[RDB_DDL_FIELD::PARTITION_NAME]->set_null();
977 } else {
978 field[RDB_DDL_FIELD::PARTITION_NAME]->set_notnull();
979 field[RDB_DDL_FIELD::PARTITION_NAME]->store(
980 partname.c_str(), partname.size(), system_charset_info);
981 }
982
983 for (uint i = 0; i < tdef->m_key_count; i++) {
984 const Rdb_key_def &kd = *tdef->m_key_descr_arr[i];
985
986 field[RDB_DDL_FIELD::INDEX_NAME]->store(kd.m_name.c_str(), kd.m_name.size(),
987 system_charset_info);
988
989 GL_INDEX_ID gl_index_id = kd.get_gl_index_id();
990 field[RDB_DDL_FIELD::COLUMN_FAMILY]->store(gl_index_id.cf_id, true);
991 field[RDB_DDL_FIELD::INDEX_NUMBER]->store(gl_index_id.index_id, true);
992 field[RDB_DDL_FIELD::INDEX_TYPE]->store(kd.m_index_type, true);
993 field[RDB_DDL_FIELD::KV_FORMAT_VERSION]->store(kd.m_kv_format_version,
994 true);
995 field[RDB_DDL_FIELD::TTL_DURATION]->store(kd.m_ttl_duration, true);
996 field[RDB_DDL_FIELD::INDEX_FLAGS]->store(kd.m_index_flags_bitmap, true);
997
998 std::string cf_name = kd.get_cf()->GetName();
999 field[RDB_DDL_FIELD::CF]->store(cf_name.c_str(), cf_name.size(),
1000 system_charset_info);
1001 ulonglong auto_incr;
1002 if (dict_manager->get_auto_incr_val(tdef->get_autoincr_gl_index_id(),
1003 &auto_incr)) {
1004 field[RDB_DDL_FIELD::AUTO_INCREMENT]->set_notnull();
1005 field[RDB_DDL_FIELD::AUTO_INCREMENT]->store(auto_incr, true);
1006 } else {
1007 field[RDB_DDL_FIELD::AUTO_INCREMENT]->set_null();
1008 }
1009
1010 ret = my_core::schema_table_store_record(m_thd, m_table);
1011 if (ret)
1012 return ret;
1013 }
1014 return HA_EXIT_SUCCESS;
1015}
1016
1017static int rdb_i_s_ddl_fill_table(my_core::THD *const thd,
1018 my_core::TABLE_LIST *const tables,
1019 my_core::Item *const cond) {
1020 DBUG_ENTER_FUNC();
1021
1022 DBUG_ASSERT(thd != nullptr);
1023 DBUG_ASSERT(tables != nullptr);
1024 DBUG_ASSERT(tables->table != nullptr);
1025
1026 int ret = 0;
1027 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
1028
1029 if (!rdb) {
1030 DBUG_RETURN(ret);
1031 }
1032
1033 Rdb_ddl_scanner ddl_arg;
1034
1035 ddl_arg.m_thd = thd;
1036 ddl_arg.m_table = tables->table;
1037
1038 Rdb_ddl_manager *ddl_manager = rdb_get_ddl_manager();
1039 DBUG_ASSERT(ddl_manager != nullptr);
1040
1041 ret = ddl_manager->scan_for_tables(&ddl_arg);
1042
1043 DBUG_RETURN(ret);
1044}
1045
1046static int rdb_i_s_ddl_init(void *const p) {
1047 DBUG_ENTER_FUNC();
1048
1049 if (prevent_myrocks_loading)
1050 DBUG_RETURN(1);
1051
1052 my_core::ST_SCHEMA_TABLE *schema;
1053
1054 DBUG_ASSERT(p != nullptr);
1055
1056 schema = (my_core::ST_SCHEMA_TABLE *)p;
1057
1058 schema->fields_info = rdb_i_s_ddl_fields_info;
1059 schema->fill_table = rdb_i_s_ddl_fill_table;
1060
1061 DBUG_RETURN(0);
1062}
1063
1064static int rdb_i_s_cfoptions_init(void *const p) {
1065 DBUG_ENTER_FUNC();
1066
1067 if (prevent_myrocks_loading)
1068 DBUG_RETURN(1);
1069
1070 DBUG_ASSERT(p != nullptr);
1071
1072 my_core::ST_SCHEMA_TABLE *schema;
1073
1074 schema = (my_core::ST_SCHEMA_TABLE *)p;
1075
1076 schema->fields_info = rdb_i_s_cfoptions_fields_info;
1077 schema->fill_table = rdb_i_s_cfoptions_fill_table;
1078
1079 DBUG_RETURN(0);
1080}
1081
1082static int rdb_i_s_global_info_init(void *const p) {
1083 DBUG_ENTER_FUNC();
1084
1085 if (prevent_myrocks_loading)
1086 DBUG_RETURN(1);
1087
1088 DBUG_ASSERT(p != nullptr);
1089
1090 my_core::ST_SCHEMA_TABLE *schema;
1091
1092 schema = reinterpret_cast<my_core::ST_SCHEMA_TABLE *>(p);
1093
1094 schema->fields_info = rdb_i_s_global_info_fields_info;
1095 schema->fill_table = rdb_i_s_global_info_fill_table;
1096
1097 DBUG_RETURN(0);
1098}
1099
1100static int rdb_i_s_compact_stats_init(void *p) {
1101 my_core::ST_SCHEMA_TABLE *schema;
1102
1103 DBUG_ENTER_FUNC();
1104
1105 if (prevent_myrocks_loading)
1106 DBUG_RETURN(1);
1107
1108 DBUG_ASSERT(p != nullptr);
1109
1110 schema = reinterpret_cast<my_core::ST_SCHEMA_TABLE *>(p);
1111
1112 schema->fields_info = rdb_i_s_compact_stats_fields_info;
1113 schema->fill_table = rdb_i_s_compact_stats_fill_table;
1114
1115 DBUG_RETURN(0);
1116}
1117
1118/* Given a path to a file return just the filename portion. */
1119static std::string rdb_filename_without_path(const std::string &path) {
1120 /* Find last slash in path */
1121 const size_t pos = path.rfind('/');
1122
1123 /* None found? Just return the original string */
1124 if (pos == std::string::npos) {
1125 return std::string(path);
1126 }
1127
1128 /* Return everything after the slash (or backslash) */
1129 return path.substr(pos + 1);
1130}
1131
1132/*
1133 Support for INFORMATION_SCHEMA.ROCKSDB_INDEX_FILE_MAP dynamic table
1134 */
1135namespace RDB_INDEX_FILE_MAP_FIELD {
1136enum {
1137 COLUMN_FAMILY = 0,
1138 INDEX_NUMBER,
1139 SST_NAME,
1140 NUM_ROWS,
1141 DATA_SIZE,
1142 ENTRY_DELETES,
1143 ENTRY_SINGLEDELETES,
1144 ENTRY_MERGES,
1145 ENTRY_OTHERS,
1146 DISTINCT_KEYS_PREFIX
1147};
1148} // namespace RDB_INDEX_FILE_MAP_FIELD
1149
1150static ST_FIELD_INFO rdb_i_s_index_file_map_fields_info[] = {
1151 /* The information_schema.rocksdb_index_file_map virtual table has four
1152 * fields:
1153 * COLUMN_FAMILY => the index's column family contained in the SST file
1154 * INDEX_NUMBER => the index id contained in the SST file
1155 * SST_NAME => the name of the SST file containing some indexes
1156 * NUM_ROWS => the number of entries of this index id in this SST file
1157 * DATA_SIZE => the data size stored in this SST file for this index id */
1158 ROCKSDB_FIELD_INFO("COLUMN_FAMILY", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1159 ROCKSDB_FIELD_INFO("INDEX_NUMBER", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1160 ROCKSDB_FIELD_INFO("SST_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1161 ROCKSDB_FIELD_INFO("NUM_ROWS", sizeof(int64_t), MYSQL_TYPE_LONGLONG, 0),
1162 ROCKSDB_FIELD_INFO("DATA_SIZE", sizeof(int64_t), MYSQL_TYPE_LONGLONG, 0),
1163 ROCKSDB_FIELD_INFO("ENTRY_DELETES", sizeof(int64_t), MYSQL_TYPE_LONGLONG,
1164 0),
1165 ROCKSDB_FIELD_INFO("ENTRY_SINGLEDELETES", sizeof(int64_t),
1166 MYSQL_TYPE_LONGLONG, 0),
1167 ROCKSDB_FIELD_INFO("ENTRY_MERGES", sizeof(int64_t), MYSQL_TYPE_LONGLONG, 0),
1168 ROCKSDB_FIELD_INFO("ENTRY_OTHERS", sizeof(int64_t), MYSQL_TYPE_LONGLONG, 0),
1169 ROCKSDB_FIELD_INFO("DISTINCT_KEYS_PREFIX", MAX_REF_PARTS * 25,
1170 MYSQL_TYPE_STRING, 0),
1171 ROCKSDB_FIELD_INFO_END};
1172
1173/* Fill the information_schema.rocksdb_index_file_map virtual table */
1174static int rdb_i_s_index_file_map_fill_table(
1175 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
1176 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
1177 DBUG_ENTER_FUNC();
1178
1179 DBUG_ASSERT(thd != nullptr);
1180 DBUG_ASSERT(tables != nullptr);
1181 DBUG_ASSERT(tables->table != nullptr);
1182
1183 int ret = 0;
1184 Field **field = tables->table->field;
1185 DBUG_ASSERT(field != nullptr);
1186
1187 /* Iterate over all the column families */
1188 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
1189
1190 if (!rdb) {
1191 DBUG_RETURN(ret);
1192 }
1193
1194 const Rdb_cf_manager &cf_manager = rdb_get_cf_manager();
1195
1196 for (const auto &cf_handle : cf_manager.get_all_cf()) {
1197 /* Grab the the properties of all the tables in the column family */
1198 rocksdb::TablePropertiesCollection table_props_collection;
1199 const rocksdb::Status s =
1200 rdb->GetPropertiesOfAllTables(cf_handle, &table_props_collection);
1201
1202 if (!s.ok()) {
1203 continue;
1204 }
1205
1206 /* Iterate over all the items in the collection, each of which contains a
1207 * name and the actual properties */
1208 for (const auto &props : table_props_collection) {
1209 /* Add the SST name into the output */
1210 const std::string sst_name = rdb_filename_without_path(props.first);
1211
1212 field[RDB_INDEX_FILE_MAP_FIELD::SST_NAME]->store(
1213 sst_name.data(), sst_name.size(), system_charset_info);
1214
1215 /* Get the __indexstats__ data out of the table property */
1216 std::vector<Rdb_index_stats> stats;
1217 Rdb_tbl_prop_coll::read_stats_from_tbl_props(props.second, &stats);
1218
1219 if (stats.empty()) {
1220 field[RDB_INDEX_FILE_MAP_FIELD::COLUMN_FAMILY]->store(-1, true);
1221 field[RDB_INDEX_FILE_MAP_FIELD::INDEX_NUMBER]->store(-1, true);
1222 field[RDB_INDEX_FILE_MAP_FIELD::NUM_ROWS]->store(-1, true);
1223 field[RDB_INDEX_FILE_MAP_FIELD::DATA_SIZE]->store(-1, true);
1224 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_DELETES]->store(-1, true);
1225 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_SINGLEDELETES]->store(-1, true);
1226 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_MERGES]->store(-1, true);
1227 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_OTHERS]->store(-1, true);
1228 } else {
1229 for (const auto &it : stats) {
1230 /* Add the index number, the number of rows, and data size to the
1231 * output */
1232 field[RDB_INDEX_FILE_MAP_FIELD::COLUMN_FAMILY]->store(
1233 it.m_gl_index_id.cf_id, true);
1234 field[RDB_INDEX_FILE_MAP_FIELD::INDEX_NUMBER]->store(
1235 it.m_gl_index_id.index_id, true);
1236 field[RDB_INDEX_FILE_MAP_FIELD::NUM_ROWS]->store(it.m_rows, true);
1237 field[RDB_INDEX_FILE_MAP_FIELD::DATA_SIZE]->store(it.m_data_size,
1238 true);
1239 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_DELETES]->store(
1240 it.m_entry_deletes, true);
1241 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_SINGLEDELETES]->store(
1242 it.m_entry_single_deletes, true);
1243 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_MERGES]->store(
1244 it.m_entry_merges, true);
1245 field[RDB_INDEX_FILE_MAP_FIELD::ENTRY_OTHERS]->store(
1246 it.m_entry_others, true);
1247
1248 std::string distinct_keys_prefix;
1249
1250 for (size_t i = 0; i < it.m_distinct_keys_per_prefix.size(); i++) {
1251 if (i > 0) {
1252 distinct_keys_prefix += ",";
1253 }
1254
1255 distinct_keys_prefix +=
1256 std::to_string(it.m_distinct_keys_per_prefix[i]);
1257 }
1258
1259 field[RDB_INDEX_FILE_MAP_FIELD::DISTINCT_KEYS_PREFIX]->store(
1260 distinct_keys_prefix.data(), distinct_keys_prefix.size(),
1261 system_charset_info);
1262
1263 /* Tell MySQL about this row in the virtual table */
1264 ret = static_cast<int>(
1265 my_core::schema_table_store_record(thd, tables->table));
1266
1267 if (ret != 0) {
1268 break;
1269 }
1270 }
1271 }
1272 }
1273 }
1274
1275 DBUG_RETURN(ret);
1276}
1277
1278/* Initialize the information_schema.rocksdb_index_file_map virtual table */
1279static int rdb_i_s_index_file_map_init(void *const p) {
1280 DBUG_ENTER_FUNC();
1281
1282 if (prevent_myrocks_loading)
1283 DBUG_RETURN(1);
1284
1285 DBUG_ASSERT(p != nullptr);
1286
1287 my_core::ST_SCHEMA_TABLE *schema;
1288
1289 schema = (my_core::ST_SCHEMA_TABLE *)p;
1290
1291 schema->fields_info = rdb_i_s_index_file_map_fields_info;
1292 schema->fill_table = rdb_i_s_index_file_map_fill_table;
1293
1294 DBUG_RETURN(0);
1295}
1296
1297/*
1298 Support for INFORMATION_SCHEMA.ROCKSDB_LOCKS dynamic table
1299 */
1300namespace RDB_LOCKS_FIELD {
1301enum { COLUMN_FAMILY_ID = 0, TRANSACTION_ID, KEY, MODE };
1302} // namespace RDB_LOCKS_FIELD
1303
1304static ST_FIELD_INFO rdb_i_s_lock_info_fields_info[] = {
1305 ROCKSDB_FIELD_INFO("COLUMN_FAMILY_ID", sizeof(uint32_t), MYSQL_TYPE_LONG,
1306 0),
1307 ROCKSDB_FIELD_INFO("TRANSACTION_ID", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1308 ROCKSDB_FIELD_INFO("KEY", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
1309 ROCKSDB_FIELD_INFO("MODE", 32, MYSQL_TYPE_STRING, 0),
1310 ROCKSDB_FIELD_INFO_END};
1311
1312/* Fill the information_schema.rocksdb_locks virtual table */
1313static int rdb_i_s_lock_info_fill_table(
1314 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
1315 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
1316 DBUG_ENTER_FUNC();
1317
1318 DBUG_ASSERT(thd != nullptr);
1319 DBUG_ASSERT(tables != nullptr);
1320 DBUG_ASSERT(tables->table != nullptr);
1321 DBUG_ASSERT(tables->table->field != nullptr);
1322
1323 int ret = 0;
1324
1325 rocksdb::TransactionDB *const rdb = rdb_get_rocksdb_db();
1326
1327 if (!rdb) {
1328 DBUG_RETURN(ret);
1329 }
1330
1331 /* cf id -> rocksdb::KeyLockInfo */
1332 std::unordered_multimap<uint32_t, rocksdb::KeyLockInfo> lock_info =
1333 rdb->GetLockStatusData();
1334
1335 for (const auto &lock : lock_info) {
1336 const uint32_t cf_id = lock.first;
1337 const auto &key_lock_info = lock.second;
1338 const auto key_hexstr = rdb_hexdump(key_lock_info.key.c_str(),
1339 key_lock_info.key.length(), FN_REFLEN);
1340
1341 for (const auto &id : key_lock_info.ids) {
1342 tables->table->field[RDB_LOCKS_FIELD::COLUMN_FAMILY_ID]->store(cf_id,
1343 true);
1344 tables->table->field[RDB_LOCKS_FIELD::TRANSACTION_ID]->store(id, true);
1345
1346 tables->table->field[RDB_LOCKS_FIELD::KEY]->store(
1347 key_hexstr.c_str(), key_hexstr.size(), system_charset_info);
1348 tables->table->field[RDB_LOCKS_FIELD::MODE]->store(
1349 key_lock_info.exclusive ? "X" : "S", 1, system_charset_info);
1350
1351 /* Tell MySQL about this row in the virtual table */
1352 ret = static_cast<int>(
1353 my_core::schema_table_store_record(thd, tables->table));
1354
1355 if (ret != 0) {
1356 break;
1357 }
1358 }
1359 }
1360
1361 DBUG_RETURN(ret);
1362}
1363
1364/* Initialize the information_schema.rocksdb_lock_info virtual table */
1365static int rdb_i_s_lock_info_init(void *const p) {
1366 DBUG_ENTER_FUNC();
1367
1368 if (prevent_myrocks_loading)
1369 DBUG_RETURN(1);
1370
1371 DBUG_ASSERT(p != nullptr);
1372
1373 my_core::ST_SCHEMA_TABLE *schema;
1374
1375 schema = (my_core::ST_SCHEMA_TABLE *)p;
1376
1377 schema->fields_info = rdb_i_s_lock_info_fields_info;
1378 schema->fill_table = rdb_i_s_lock_info_fill_table;
1379
1380 DBUG_RETURN(0);
1381}
1382
1383/*
1384 Support for INFORMATION_SCHEMA.ROCKSDB_TRX dynamic table
1385 */
1386namespace RDB_TRX_FIELD {
1387enum {
1388 TRANSACTION_ID = 0,
1389 STATE,
1390 NAME,
1391 WRITE_COUNT,
1392 LOCK_COUNT,
1393 TIMEOUT_SEC,
1394 WAITING_KEY,
1395 WAITING_COLUMN_FAMILY_ID,
1396 IS_REPLICATION,
1397 SKIP_TRX_API,
1398 READ_ONLY,
1399 HAS_DEADLOCK_DETECTION,
1400 NUM_ONGOING_BULKLOAD,
1401 THREAD_ID,
1402 QUERY
1403};
1404} // namespace RDB_TRX_FIELD
1405
1406static ST_FIELD_INFO rdb_i_s_trx_info_fields_info[] = {
1407 ROCKSDB_FIELD_INFO("TRANSACTION_ID", sizeof(ulonglong), MYSQL_TYPE_LONGLONG,
1408 0),
1409 ROCKSDB_FIELD_INFO("STATE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1410 ROCKSDB_FIELD_INFO("NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1411 ROCKSDB_FIELD_INFO("WRITE_COUNT", sizeof(ulonglong), MYSQL_TYPE_LONGLONG,
1412 0),
1413 ROCKSDB_FIELD_INFO("LOCK_COUNT", sizeof(ulonglong), MYSQL_TYPE_LONGLONG, 0),
1414 ROCKSDB_FIELD_INFO("TIMEOUT_SEC", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1415 ROCKSDB_FIELD_INFO("WAITING_KEY", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
1416 ROCKSDB_FIELD_INFO("WAITING_COLUMN_FAMILY_ID", sizeof(uint32_t),
1417 MYSQL_TYPE_LONG, 0),
1418 ROCKSDB_FIELD_INFO("IS_REPLICATION", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1419 ROCKSDB_FIELD_INFO("SKIP_TRX_API", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1420 ROCKSDB_FIELD_INFO("READ_ONLY", sizeof(uint32_t), MYSQL_TYPE_LONG, 0),
1421 ROCKSDB_FIELD_INFO("HAS_DEADLOCK_DETECTION", sizeof(uint32_t),
1422 MYSQL_TYPE_LONG, 0),
1423 ROCKSDB_FIELD_INFO("NUM_ONGOING_BULKLOAD", sizeof(uint32_t),
1424 MYSQL_TYPE_LONG, 0),
1425 ROCKSDB_FIELD_INFO("THREAD_ID", sizeof(ulong), MYSQL_TYPE_LONG, 0),
1426 ROCKSDB_FIELD_INFO("QUERY", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1427 ROCKSDB_FIELD_INFO_END};
1428
1429/* Fill the information_schema.rocksdb_trx virtual table */
1430static int rdb_i_s_trx_info_fill_table(
1431 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
1432 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
1433 DBUG_ENTER_FUNC();
1434
1435 DBUG_ASSERT(thd != nullptr);
1436 DBUG_ASSERT(tables != nullptr);
1437 DBUG_ASSERT(tables->table != nullptr);
1438 DBUG_ASSERT(tables->table->field != nullptr);
1439
1440 int ret = 0;
1441 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
1442
1443 if (!rdb) {
1444 DBUG_RETURN(ret);
1445 }
1446
1447 const std::vector<Rdb_trx_info> &all_trx_info = rdb_get_all_trx_info();
1448
1449 for (const auto &info : all_trx_info) {
1450 auto name_hexstr =
1451 rdb_hexdump(info.name.c_str(), info.name.length(), NAME_LEN);
1452 auto key_hexstr = rdb_hexdump(info.waiting_key.c_str(),
1453 info.waiting_key.length(), FN_REFLEN);
1454
1455 tables->table->field[RDB_TRX_FIELD::TRANSACTION_ID]->store(info.trx_id,
1456 true);
1457 tables->table->field[RDB_TRX_FIELD::STATE]->store(
1458 info.state.c_str(), info.state.length(), system_charset_info);
1459 tables->table->field[RDB_TRX_FIELD::NAME]->store(
1460 name_hexstr.c_str(), name_hexstr.length(), system_charset_info);
1461 tables->table->field[RDB_TRX_FIELD::WRITE_COUNT]->store(info.write_count,
1462 true);
1463 tables->table->field[RDB_TRX_FIELD::LOCK_COUNT]->store(info.lock_count,
1464 true);
1465 tables->table->field[RDB_TRX_FIELD::TIMEOUT_SEC]->store(info.timeout_sec,
1466 false);
1467 tables->table->field[RDB_TRX_FIELD::WAITING_KEY]->store(
1468 key_hexstr.c_str(), key_hexstr.length(), system_charset_info);
1469 tables->table->field[RDB_TRX_FIELD::WAITING_COLUMN_FAMILY_ID]->store(
1470 info.waiting_cf_id, true);
1471 tables->table->field[RDB_TRX_FIELD::IS_REPLICATION]->store(
1472 info.is_replication, false);
1473 tables->table->field[RDB_TRX_FIELD::SKIP_TRX_API]->store(info.skip_trx_api,
1474 false);
1475 tables->table->field[RDB_TRX_FIELD::READ_ONLY]->store(info.read_only,
1476 false);
1477 tables->table->field[RDB_TRX_FIELD::HAS_DEADLOCK_DETECTION]->store(
1478 info.deadlock_detect, false);
1479 tables->table->field[RDB_TRX_FIELD::NUM_ONGOING_BULKLOAD]->store(
1480 info.num_ongoing_bulk_load, false);
1481 tables->table->field[RDB_TRX_FIELD::THREAD_ID]->store(info.thread_id, true);
1482 tables->table->field[RDB_TRX_FIELD::QUERY]->store(
1483 info.query_str.c_str(), info.query_str.length(), system_charset_info);
1484
1485 /* Tell MySQL about this row in the virtual table */
1486 ret = static_cast<int>(
1487 my_core::schema_table_store_record(thd, tables->table));
1488
1489 if (ret != 0) {
1490 break;
1491 }
1492 }
1493
1494 DBUG_RETURN(ret);
1495}
1496
1497/* Initialize the information_schema.rocksdb_trx_info virtual table */
1498static int rdb_i_s_trx_info_init(void *const p) {
1499 DBUG_ENTER_FUNC();
1500
1501 if (prevent_myrocks_loading)
1502 DBUG_RETURN(1);
1503
1504 DBUG_ASSERT(p != nullptr);
1505
1506 my_core::ST_SCHEMA_TABLE *schema;
1507
1508 schema = (my_core::ST_SCHEMA_TABLE *)p;
1509
1510 schema->fields_info = rdb_i_s_trx_info_fields_info;
1511 schema->fill_table = rdb_i_s_trx_info_fill_table;
1512
1513 DBUG_RETURN(0);
1514}
1515
1516/*
1517 Support for INFORMATION_SCHEMA.ROCKSDB_DEADLOCK dynamic table
1518 */
1519namespace RDB_DEADLOCK_FIELD {
1520enum {
1521 DEADLOCK_ID = 0,
1522 TRANSACTION_ID,
1523 CF_NAME,
1524 WAITING_KEY,
1525 LOCK_TYPE,
1526 INDEX_NAME,
1527 TABLE_NAME,
1528 ROLLED_BACK
1529};
1530} // namespace RDB_TRX_FIELD
1531
1532static ST_FIELD_INFO rdb_i_s_deadlock_info_fields_info[] = {
1533 ROCKSDB_FIELD_INFO("DEADLOCK_ID", sizeof(ulonglong), MYSQL_TYPE_LONGLONG,
1534 0),
1535 ROCKSDB_FIELD_INFO("TRANSACTION_ID", sizeof(ulonglong), MYSQL_TYPE_LONGLONG,
1536 0),
1537 ROCKSDB_FIELD_INFO("CF_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1538 ROCKSDB_FIELD_INFO("WAITING_KEY", FN_REFLEN + 1, MYSQL_TYPE_STRING, 0),
1539 ROCKSDB_FIELD_INFO("LOCK_TYPE", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1540 ROCKSDB_FIELD_INFO("INDEX_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1541 ROCKSDB_FIELD_INFO("TABLE_NAME", NAME_LEN + 1, MYSQL_TYPE_STRING, 0),
1542 ROCKSDB_FIELD_INFO("ROLLED_BACK", sizeof(ulonglong), MYSQL_TYPE_LONGLONG,
1543 0),
1544 ROCKSDB_FIELD_INFO_END};
1545
1546/* Fill the information_schema.rocksdb_trx virtual table */
1547static int rdb_i_s_deadlock_info_fill_table(
1548 my_core::THD *const thd, my_core::TABLE_LIST *const tables,
1549 my_core::Item *const cond MY_ATTRIBUTE((__unused__))) {
1550 DBUG_ENTER_FUNC();
1551
1552 DBUG_ASSERT(thd != nullptr);
1553 DBUG_ASSERT(tables != nullptr);
1554 DBUG_ASSERT(tables->table != nullptr);
1555 DBUG_ASSERT(tables->table->field != nullptr);
1556
1557 static const std::string str_exclusive("EXCLUSIVE");
1558 static const std::string str_shared("SHARED");
1559
1560 int ret = 0;
1561 rocksdb::DB *const rdb = rdb_get_rocksdb_db();
1562
1563 if (!rdb) {
1564 DBUG_RETURN(ret);
1565 }
1566
1567 const std::vector<Rdb_deadlock_info> &all_dl_info = rdb_get_deadlock_info();
1568
1569 ulonglong id = 0;
1570 for (const auto &info : all_dl_info) {
1571 for (const auto &trx_info : info.path) {
1572 tables->table->field[RDB_DEADLOCK_FIELD::DEADLOCK_ID]->store(id, true);
1573 tables->table->field[RDB_DEADLOCK_FIELD::TRANSACTION_ID]->store(
1574 trx_info.trx_id, true);
1575 tables->table->field[RDB_DEADLOCK_FIELD::CF_NAME]->store(
1576 trx_info.cf_name.c_str(), trx_info.cf_name.length(),
1577 system_charset_info);
1578 tables->table->field[RDB_DEADLOCK_FIELD::WAITING_KEY]->store(
1579 trx_info.waiting_key.c_str(), trx_info.waiting_key.length(),
1580 system_charset_info);
1581 if (trx_info.exclusive_lock) {
1582 tables->table->field[RDB_DEADLOCK_FIELD::LOCK_TYPE]->store(
1583 str_exclusive.c_str(), str_exclusive.length(), system_charset_info);
1584 } else {
1585 tables->table->field[RDB_DEADLOCK_FIELD::LOCK_TYPE]->store(
1586 str_shared.c_str(), str_shared.length(), system_charset_info);
1587 }
1588 tables->table->field[RDB_DEADLOCK_FIELD::INDEX_NAME]->store(
1589 trx_info.index_name.c_str(), trx_info.index_name.length(),
1590 system_charset_info);
1591 tables->table->field[RDB_DEADLOCK_FIELD::TABLE_NAME]->store(
1592 trx_info.table_name.c_str(), trx_info.table_name.length(),
1593 system_charset_info);
1594 tables->table->field[RDB_DEADLOCK_FIELD::ROLLED_BACK]->store(
1595 trx_info.trx_id == info.victim_trx_id, true);
1596
1597 /* Tell MySQL about this row in the virtual table */
1598 ret = static_cast<int>(
1599 my_core::schema_table_store_record(thd, tables->table));
1600
1601 if (ret != 0) {
1602 break;
1603 }
1604 }
1605 id++;
1606 }
1607
1608 DBUG_RETURN(ret);
1609}
1610
1611/* Initialize the information_schema.rocksdb_trx_info virtual table */
1612static int rdb_i_s_deadlock_info_init(void *const p) {
1613 DBUG_ENTER_FUNC();
1614
1615 DBUG_ASSERT(p != nullptr);
1616
1617 my_core::ST_SCHEMA_TABLE *schema;
1618
1619 schema = (my_core::ST_SCHEMA_TABLE *)p;
1620
1621 schema->fields_info = rdb_i_s_deadlock_info_fields_info;
1622 schema->fill_table = rdb_i_s_deadlock_info_fill_table;
1623
1624 DBUG_RETURN(0);
1625}
1626
1627static int rdb_i_s_deinit(void *p MY_ATTRIBUTE((__unused__))) {
1628 DBUG_ENTER_FUNC();
1629 DBUG_RETURN(0);
1630}
1631
1632static struct st_mysql_information_schema rdb_i_s_info = {
1633 MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
1634
1635struct st_maria_plugin rdb_i_s_cfstats = {
1636 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1637 &rdb_i_s_info,
1638 "ROCKSDB_CFSTATS",
1639 "Facebook",
1640 "RocksDB column family stats",
1641 PLUGIN_LICENSE_GPL,
1642 rdb_i_s_cfstats_init,
1643 rdb_i_s_deinit,
1644 0x0001, /* version number (0.1) */
1645 nullptr, /* status variables */
1646 nullptr, /* system variables */
1647 nullptr, /* config options */
1648 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1649};
1650
1651struct st_maria_plugin rdb_i_s_dbstats = {
1652 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1653 &rdb_i_s_info,
1654 "ROCKSDB_DBSTATS",
1655 "Facebook",
1656 "RocksDB database stats",
1657 PLUGIN_LICENSE_GPL,
1658 rdb_i_s_dbstats_init,
1659 rdb_i_s_deinit,
1660 0x0001, /* version number (0.1) */
1661 nullptr, /* status variables */
1662 nullptr, /* system variables */
1663 nullptr, /* config options */
1664 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1665};
1666
1667struct st_maria_plugin rdb_i_s_perf_context = {
1668 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1669 &rdb_i_s_info,
1670 "ROCKSDB_PERF_CONTEXT",
1671 "Facebook",
1672 "RocksDB perf context stats",
1673 PLUGIN_LICENSE_GPL,
1674 rdb_i_s_perf_context_init,
1675 rdb_i_s_deinit,
1676 0x0001, /* version number (0.1) */
1677 nullptr, /* status variables */
1678 nullptr, /* system variables */
1679 nullptr, /* config options */
1680 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1681};
1682
1683struct st_maria_plugin rdb_i_s_perf_context_global = {
1684 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1685 &rdb_i_s_info,
1686 "ROCKSDB_PERF_CONTEXT_GLOBAL",
1687 "Facebook",
1688 "RocksDB perf context stats (all)",
1689 PLUGIN_LICENSE_GPL,
1690 rdb_i_s_perf_context_global_init,
1691 rdb_i_s_deinit,
1692 0x0001, /* version number (0.1) */
1693 nullptr, /* status variables */
1694 nullptr, /* system variables */
1695 nullptr, /* config options */
1696 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1697};
1698
1699struct st_maria_plugin rdb_i_s_cfoptions = {
1700 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1701 &rdb_i_s_info,
1702 "ROCKSDB_CF_OPTIONS",
1703 "Facebook",
1704 "RocksDB column family options",
1705 PLUGIN_LICENSE_GPL,
1706 rdb_i_s_cfoptions_init,
1707 rdb_i_s_deinit,
1708 0x0001, /* version number (0.1) */
1709 nullptr, /* status variables */
1710 nullptr, /* system variables */
1711 nullptr, /* config options */
1712 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1713};
1714
1715struct st_maria_plugin rdb_i_s_global_info = {
1716 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1717 &rdb_i_s_info,
1718 "ROCKSDB_GLOBAL_INFO",
1719 "Facebook",
1720 "RocksDB global info",
1721 PLUGIN_LICENSE_GPL,
1722 rdb_i_s_global_info_init,
1723 rdb_i_s_deinit,
1724 0x0001, /* version number (0.1) */
1725 nullptr, /* status variables */
1726 nullptr, /* system variables */
1727 nullptr, /* config options */
1728 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1729};
1730
1731struct st_maria_plugin rdb_i_s_compact_stats = {
1732 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1733 &rdb_i_s_info,
1734 "ROCKSDB_COMPACTION_STATS",
1735 "Facebook",
1736 "RocksDB compaction stats",
1737 PLUGIN_LICENSE_GPL,
1738 rdb_i_s_compact_stats_init,
1739 rdb_i_s_deinit,
1740 0x0001, /* version number (0.1) */
1741 nullptr, /* status variables */
1742 nullptr, /* system variables */
1743 nullptr, /* config options */
1744 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1745};
1746
1747struct st_maria_plugin rdb_i_s_ddl = {
1748 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1749 &rdb_i_s_info,
1750 "ROCKSDB_DDL",
1751 "Facebook",
1752 "RocksDB Data Dictionary",
1753 PLUGIN_LICENSE_GPL,
1754 rdb_i_s_ddl_init,
1755 rdb_i_s_deinit,
1756 0x0001, /* version number (0.1) */
1757 nullptr, /* status variables */
1758 nullptr, /* system variables */
1759 nullptr, /* config options */
1760 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1761};
1762
1763struct st_maria_plugin rdb_i_s_index_file_map = {
1764 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1765 &rdb_i_s_info,
1766 "ROCKSDB_INDEX_FILE_MAP",
1767 "Facebook",
1768 "RocksDB index file map",
1769 PLUGIN_LICENSE_GPL,
1770 rdb_i_s_index_file_map_init,
1771 rdb_i_s_deinit,
1772 0x0001, /* version number (0.1) */
1773 nullptr, /* status variables */
1774 nullptr, /* system variables */
1775 nullptr, /* config options */
1776 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1777};
1778
1779struct st_maria_plugin rdb_i_s_lock_info = {
1780 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1781 &rdb_i_s_info,
1782 "ROCKSDB_LOCKS",
1783 "Facebook",
1784 "RocksDB lock information",
1785 PLUGIN_LICENSE_GPL,
1786 rdb_i_s_lock_info_init,
1787 nullptr,
1788 0x0001, /* version number (0.1) */
1789 nullptr, /* status variables */
1790 nullptr, /* system variables */
1791 nullptr, /* config options */
1792 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1793};
1794
1795struct st_maria_plugin rdb_i_s_trx_info = {
1796 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1797 &rdb_i_s_info,
1798 "ROCKSDB_TRX",
1799 "Facebook",
1800 "RocksDB transaction information",
1801 PLUGIN_LICENSE_GPL,
1802 rdb_i_s_trx_info_init,
1803 nullptr,
1804 0x0001, /* version number (0.1) */
1805 nullptr, /* status variables */
1806 nullptr, /* system variables */
1807 nullptr, /* config options */
1808 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1809};
1810
1811struct st_maria_plugin rdb_i_s_deadlock_info = {
1812 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1813 &rdb_i_s_info,
1814 "ROCKSDB_DEADLOCK",
1815 "Facebook",
1816 "RocksDB transaction information",
1817 PLUGIN_LICENSE_GPL,
1818 rdb_i_s_deadlock_info_init,
1819 nullptr,
1820 0x0001, /* version number (0.1) */
1821 nullptr, /* status variables */
1822 nullptr, /* system variables */
1823 nullptr, /* config options */
1824 MYROCKS_MARIADB_PLUGIN_MATURITY_LEVEL
1825};
1826} // namespace myrocks
1827