diff --git a/include/ircd/db/database/rocksdb.h b/include/ircd/db/database/rocksdb.h index 668b166c1..2a72f1a13 100644 --- a/include/ircd/db/database/rocksdb.h +++ b/include/ircd/db/database/rocksdb.h @@ -34,6 +34,7 @@ namespace rocksdb struct PerfContext; struct IOStatsContext; struct LiveFileMetaData; + struct SstFileWriter; } // diff --git a/include/ircd/db/database/sst.h b/include/ircd/db/database/sst.h index dc72b5b0b..289dd0cda 100644 --- a/include/ircd/db/database/sst.h +++ b/include/ircd/db/database/sst.h @@ -14,15 +14,9 @@ struct ircd::db::database::sst { struct info; + struct dump; - static void dump(const vector_view &args); -}; - -struct ircd::db::database::sst::writer -{ - using key_range = std::pair; - - writer(const database &, const column &, const key_range & = {}); + static void tool(const vector_view &args); }; /// Get info about an SST file. @@ -42,6 +36,8 @@ struct ircd::db::database::sst::info uint64_t num_reads {0}; int level {-1}; bool compacting {false}; + int32_t version {-1}; + uint64_t entries {0}; info() = default; info(rocksdb::LiveFileMetaData &&); @@ -54,3 +50,14 @@ struct ircd::db::database::sst::info::vector vector() = default; explicit vector(const database &); }; + +struct ircd::db::database::sst::dump +{ + using key_range = std::pair; + + sst::info info; + + dump(db::column, const key_range & = {}, const string_view &path = {}); + dump(dump &&) = delete; + dump(const dump &) = delete; +}; diff --git a/ircd/db.cc b/ircd/db.cc index 5e68f1f8b..b54088705 100644 --- a/ircd/db.cc +++ b/ircd/db.cc @@ -2490,7 +2490,7 @@ const noexcept // void -ircd::db::database::sst::dump(const vector_view &args) +ircd::db::database::sst::tool(const vector_view &args) { static const size_t ARG_MAX {16}; static const size_t ARG_MAX_LEN {256}; @@ -2523,6 +2523,64 @@ ircd::db::database::sst::dump(const vector_view &args) }; } +// +// sst::dump::dump +// + +ircd::db::database::sst::dump::dump(db::column column, + const key_range &range, + const string_view &path_) +{ + const database &d(column); + database::column &c(column); + std::string path{path_}; + if(path.empty()) + { + const string_view path_parts[] + { + fs::get(fs::DB), db::name(d), db::name(c) + }; + + path = fs::make_path(path_parts); + } + + rocksdb::Options opts(d.d->GetOptions(c)); + rocksdb::EnvOptions eopts(opts); + rocksdb::SstFileWriter writer + { + eopts, opts, c + }; + + throw_on_error + { + writer.Open(path) + }; + + size_t i(0); + for(auto it(column.begin()); it != column.end(); ++it, ++i) + throw_on_error + { + writer.Put(slice(it->first), slice(it->second)) + }; + + rocksdb::ExternalSstFileInfo info; + if(i) + throw_on_error + { + writer.Finish(&info) + }; + + this->info.column = db::name(column); + this->info.path = std::move(info.file_path); + this->info.min_key = std::move(info.smallest_key); + this->info.max_key = std::move(info.largest_key); + this->info.min_seq = info.sequence_number; + this->info.max_seq = info.sequence_number; + this->info.size = info.file_size; + this->info.entries = info.num_entries; + this->info.version = info.version; +} + // // sst::info::vector // @@ -2541,7 +2599,7 @@ ircd::db::database::sst::info::vector::vector(const database &d) } // -// fileinfo::fileinfo +// sst::info::info // ircd::db::database::sst::info::info(const database &d, diff --git a/modules/console.cc b/modules/console.cc index d7fa9e0ae..cb7968737 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -1937,7 +1937,7 @@ catch(const std::out_of_range &e) } bool -console_cmd__db__sstdump(opt &out, const string_view &line) +console_cmd__db__sst(opt &out, const string_view &line) { string_view buf[16]; const vector_view args @@ -1945,7 +1945,54 @@ console_cmd__db__sstdump(opt &out, const string_view &line) buf, tokens(line, " ", buf) }; - db::database::sst::dump(args); + db::database::sst::tool(args); + return true; +} + +bool +console_cmd__db__sst__dump(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "dbname", "column", "begin", "end", "path" + }}; + + const auto dbname + { + param.at("dbname") + }; + + const auto colname + { + param.at("column") + }; + + const auto begin + { + param["begin"] + }; + + const auto end + { + param["end"] + }; + + const auto path + { + param["path"] + }; + + auto &database + { + db::database::get(dbname) + }; + + db::column column + { + database, colname + }; + + db::database::sst::dump(column, {begin, end}, path); return true; }