BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
snapshot.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Peter Conrad, and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
25 
27 
28 #include <fc/io/fstream.hpp>
29 
30 using namespace graphene::snapshot_plugin;
31 using std::string;
32 using std::vector;
33 
34 namespace bpo = boost::program_options;
35 
36 static const char* OPT_BLOCK_NUM = "snapshot-at-block";
37 static const char* OPT_BLOCK_TIME = "snapshot-at-time";
38 static const char* OPT_DEST = "snapshot-to";
39 
40 void snapshot_plugin::plugin_set_program_options(
41  boost::program_options::options_description& command_line_options,
42  boost::program_options::options_description& config_file_options)
43 {
44  command_line_options.add_options()
45  (OPT_BLOCK_NUM, bpo::value<uint32_t>(), "Block number after which to do a snapshot")
46  (OPT_BLOCK_TIME, bpo::value<string>(), "Block time (ISO format) after which to do a snapshot")
47  (OPT_DEST, bpo::value<string>(), "Pathname of JSON file where to store the snapshot")
48  ;
49  config_file_options.add(command_line_options);
50 }
51 
52 std::string snapshot_plugin::plugin_name()const
53 {
54  return "snapshot";
55 }
56 
57 std::string snapshot_plugin::plugin_description()const
58 {
59  return "Create snapshots at a specified time or block number.";
60 }
61 
62 void snapshot_plugin::plugin_initialize(const boost::program_options::variables_map& options)
63 { try {
64  ilog("snapshot plugin: plugin_initialize() begin");
65 
66  if( options.count(OPT_BLOCK_NUM) > 0 || options.count(OPT_BLOCK_TIME) > 0 )
67  {
68  FC_ASSERT( options.count(OPT_DEST) > 0,
69  "Must specify snapshot-to in addition to snapshot-at-block or snapshot-at-time!" );
70  dest = options[OPT_DEST].as<std::string>();
71  if( options.count(OPT_BLOCK_NUM) > 0 )
72  snapshot_block = options[OPT_BLOCK_NUM].as<uint32_t>();
73  if( options.count(OPT_BLOCK_TIME) > 0 )
74  snapshot_time = fc::time_point_sec::from_iso_string( options[OPT_BLOCK_TIME].as<std::string>() );
75  // connect with no group specified to process after the ones with a group specified
76  database().applied_block.connect( [&]( const graphene::chain::signed_block& b ) {
77  check_snapshot( b );
78  });
79  }
80  else
81  ilog("snapshot plugin is not enabled because neither snapshot-at-block nor snapshot-at-time is specified");
82 
83  ilog("snapshot plugin: plugin_initialize() end");
85 
86 static void create_snapshot( const graphene::chain::database& db, const fc::path& dest )
87 {
88  ilog("snapshot plugin: creating snapshot");
89  fc::ofstream out;
90  try
91  {
92  out.open( dest );
93  }
94  catch ( fc::exception& e )
95  {
96  wlog( "Failed to open snapshot destination: ${ex}", ("ex",e) );
97  return;
98  }
99  for( uint32_t space_id = 0; space_id < 256; space_id++ )
100  for( uint32_t type_id = 0; type_id < 256; type_id++ )
101  {
102  try
103  {
104  db.get_index( (uint8_t)space_id, (uint8_t)type_id );
105  }
106  catch (fc::assert_exception& e)
107  {
108  continue;
109  }
110  auto& index = db.get_index( (uint8_t)space_id, (uint8_t)type_id );
111  index.inspect_all_objects( [&out]( const graphene::db::object& o ) {
112  out << fc::json::to_string( o.to_variant() ) << '\n';
113  });
114  }
115  out.close();
116  ilog("snapshot plugin: created snapshot");
117 }
118 
119 void snapshot_plugin::check_snapshot( const graphene::chain::signed_block& b )
120 { try {
121  uint32_t current_block = b.block_num();
122  if( (last_block < snapshot_block && snapshot_block <= current_block)
123  || (last_time < snapshot_time && snapshot_time <= b.timestamp) )
124  create_snapshot( database(), dest );
125  last_block = current_block;
126  last_time = b.timestamp;
127 } FC_LOG_AND_RETHROW() }
snapshot.hpp
graphene::chain::database
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
wlog
#define wlog(FORMAT,...)
Definition: logger.hpp:123
fc::exception
Used to generate a useful error report when an exception is thrown.
Definition: exception.hpp:56
graphene::snapshot_plugin
Definition: snapshot.hpp:31
database.hpp
graphene::app::plugin::database
chain::database & database()
Definition: plugin.hpp:115
fc::time_point_sec::from_iso_string
static time_point_sec from_iso_string(const std::string &s)
Definition: time.cpp:35
FC_LOG_AND_RETHROW
#define FC_LOG_AND_RETHROW()
Definition: exception.hpp:395
graphene::chain::database::applied_block
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:624
fc::ofstream::open
void open(const fc::path &file, std::ios_base::openmode m=std::ios_base::out|std::ios_base::binary)
Definition: fstream.cpp:32
fc::json::to_string
static string to_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:650
graphene::protocol::block_header::block_num
uint32_t block_num() const
Definition: block.hpp:34
graphene::db::object::to_variant
virtual fc::variant to_variant() const =0
fc::ofstream::close
void close()
Definition: fstream.cpp:48
fc::path
wraps boost::filesystem::path to provide platform independent path manipulation.
Definition: filesystem.hpp:28
ilog
#define ilog(FORMAT,...)
Definition: logger.hpp:117
graphene::protocol::block_header::timestamp
fc::time_point_sec timestamp
Definition: block.hpp:35
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
fc::ofstream
Definition: fstream.hpp:9
fstream.hpp
graphene::db::object_database::get_index
const index & get_index() const
Definition: object_database.hpp:83
graphene::protocol::signed_block
Definition: block.hpp:64
fc::typelist::index
typename impl::zip< typename impl::make_sequence< length< List >()>::type, List >::type index
Definition: typelist.hpp:225
graphene::db::object
base for all database objects
Definition: object.hpp:61