Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Add command line option --snapshot-to-json 馃摝 #11058

Open
wants to merge 2 commits into
base: develop-boxed
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions libraries/chain/include/eosio/chain/snapshot.hpp
Expand Up @@ -342,7 +342,22 @@ namespace eosio { namespace chain {
std::streampos header_pos;
std::streampos section_pos;
uint64_t row_count;
};

class ostream_json_snapshot_writer : public snapshot_writer {
public:
explicit ostream_json_snapshot_writer(std::ostream& snapshot);

void write_start_section( const std::string& section_name ) override;
void write_row( const detail::abstract_snapshot_row_writer& row_writer ) override;
void write_end_section() override;
void finalize();

static const uint32_t magic_number = 0x30510550;

private:
detail::ostream_wrapper snapshot;
uint64_t row_count;
};

class istream_snapshot_reader : public snapshot_reader {
Expand Down
39 changes: 39 additions & 0 deletions libraries/chain/snapshot.cpp
@@ -1,6 +1,7 @@
#include <eosio/chain/snapshot.hpp>
#include <eosio/chain/exceptions.hpp>
#include <fc/scoped_exit.hpp>
#include <fc/io/json.hpp>

namespace eosio { namespace chain {

Expand Down Expand Up @@ -190,6 +191,44 @@ void ostream_snapshot_writer::finalize() {
snapshot.write((char*)&end_marker, sizeof(end_marker));
}

ostream_json_snapshot_writer::ostream_json_snapshot_writer(std::ostream& snapshot)
:snapshot(snapshot)
,row_count(0)
{
snapshot << "{\n";
// write magic number
auto totem = magic_number;
snapshot << "\"magic_number\":" << fc::json::to_string(totem, fc::time_point::maximum()) << "\n";

// write version
auto version = current_snapshot_version;
snapshot << ",\"version\":" << fc::json::to_string(version, fc::time_point::maximum()) << "\n";
}

void ostream_json_snapshot_writer::write_start_section( const std::string& section_name )
{
snapshot.inner << "," << fc::json::to_string(section_name, fc::time_point::maximum()) << ":{\n";
linhuang-blockone marked this conversation as resolved.
Show resolved Hide resolved
}

void ostream_json_snapshot_writer::write_row( const detail::abstract_snapshot_row_writer& row_writer ) {
const auto yield = [&](size_t s) {};

if(row_count != 0) snapshot.inner << ",";
snapshot.inner << "\"row_" << row_count << "\":" << fc::json::to_string(row_writer.to_variant(), yield) << "\n";
++row_count;
}

void ostream_json_snapshot_writer::write_end_section( ) {
snapshot.inner << "}\n";
row_count = 0;
}

void ostream_json_snapshot_writer::finalize() {
snapshot.inner << "}\n";
snapshot.inner.flush();
}


istream_snapshot_reader::istream_snapshot_reader(std::istream& snapshot)
:snapshot(snapshot)
,header_pos(snapshot.tellg())
Expand Down
54 changes: 53 additions & 1 deletion plugins/chain_plugin/chain_plugin.cpp
Expand Up @@ -427,6 +427,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
"print build environment information to console as JSON and exit")
("extract-build-info", bpo::value<bfs::path>(),
"extract build environment information as JSON, write into specified file, and exit")
("snapshot-to-json", bpo::value<bfs::path>(),
"convert snapshot to JSON format, and exit")
("force-all-checks", bpo::bool_switch()->default_value(false),
"do not skip any validation checks while replaying blocks (useful for replaying blocks from untrusted source)")
("disable-replay-opts", bpo::bool_switch()->default_value(false),
Expand Down Expand Up @@ -963,6 +965,57 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
EOS_THROW( extract_genesis_state_exception, "extracted genesis state from blocks.log" );
}

std::optional<chain_id_type> chain_id;
if( options.count("snapshot-to-json") ) {
linhuang-blockone marked this conversation as resolved.
Show resolved Hide resolved
my->snapshot_path = options.at( "snapshot-to-json" ).as<bfs::path>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please move that code to the separate method

EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception,
"Cannot load snapshot, ${name} does not exist", ("name", my->snapshot_path->generic_string()) );

// recover genesis information from the snapshot
// used for validation code below
auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary));
istream_snapshot_reader reader(infile);
reader.validate();
chain_id = controller::extract_chain_id(reader);
infile.close();

boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
my->chain_config->state_dir = temp_dir / "state";
my->blocks_dir = temp_dir / "blocks";
my->chain_config->blog.log_dir = my->blocks_dir;
try {
auto shutdown = [](){ return app().quit(); };
auto check_shutdown = [](){ return app().is_quiting(); };
auto infile = std::ifstream(my->snapshot_path->generic_string(), (std::ios::in | std::ios::binary));
auto reader = std::make_shared<istream_snapshot_reader>(infile);
my->chain.emplace( *my->chain_config, std::move(pfs), *chain_id );
my->chain->add_indices();
my->chain->startup(shutdown, check_shutdown, reader);
infile.close();
app().quit(); // shutdown as we will be finished after writing the snapshot

ilog("Writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json"));
auto snap_out = std::ofstream( my->snapshot_path->generic_string() + ".json", (std::ios::out) );
auto writer = std::make_shared<ostream_json_snapshot_writer>( snap_out );
my->chain->write_snapshot( writer );
writer->finalize();
snap_out.flush();
snap_out.close();
} catch (const database_guard_exception& e) {
log_guard_exception(e);
// make sure to properly close the db
my->chain.reset();
fc::remove_all(temp_dir);
throw;
}
my->chain.reset();
fc::remove_all(temp_dir);
ilog("Completed writing snapshot: ${s}", ("s", my->snapshot_path->generic_string() + ".json"));
ilog("==== Ignore any additional log messages. ====");

EOS_THROW( node_management_success, "extracted json from snapshot" );
}

// move fork_db to new location
upgrade_from_reversible_to_fork_db( my.get() );

Expand All @@ -983,7 +1036,6 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
wlog( "The --truncate-at-block option can only be used with --hard-replay-blockchain." );
}

std::optional<chain_id_type> chain_id;
if (options.count( "snapshot" )) {
my->snapshot_path = options.at( "snapshot" ).as<bfs::path>();
EOS_ASSERT( fc::exists(*my->snapshot_path), plugin_config_exception,
Expand Down