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