27 #include <boost/endian/buffers.hpp> 29 namespace graphene {
namespace chain {
37 boost::endian::little_uint64_buf_t
block_pos;
44 namespace graphene {
namespace chain {
49 _block_num_to_pos.exceptions(std::ios_base::failbit | std::ios_base::badbit);
50 _blocks.exceptions(std::ios_base::failbit | std::ios_base::badbit);
52 _index_filename = dbdir /
"index";
55 _block_num_to_pos.open( _index_filename.generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
56 _blocks.open( (dbdir/
"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
60 _block_num_to_pos.open( _index_filename.generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
61 _blocks.open( (dbdir/
"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
67 return _blocks.is_open();
73 _block_num_to_pos.close();
79 _block_num_to_pos.flush();
88 elog(
"id argument of block_database::store() was not initialized for block ${id}", (
"id",
id) );
92 _blocks.seekp( 0, _blocks.end );
97 _blocks.write( vec.data(), vec.size() );
98 _block_num_to_pos.write( (
char*)&e,
sizeof(e) );
105 _block_num_to_pos.seekg( 0, _block_num_to_pos.end );
106 if ( _block_num_to_pos.tellg() <= index_pos )
107 FC_THROW_EXCEPTION(fc::key_not_found_exception,
"Block ${id} not contained in block database", (
"id",
id));
109 _block_num_to_pos.seekg( index_pos );
110 _block_num_to_pos.read( (
char*)&e,
sizeof(e) );
112 if( e.block_id ==
id )
116 _block_num_to_pos.write( (
char*)&e,
sizeof(e) );
127 _block_num_to_pos.seekg( 0, _block_num_to_pos.end );
128 if ( _block_num_to_pos.tellg() < int64_t(index_pos +
sizeof(e)) )
130 _block_num_to_pos.seekg( index_pos );
131 _block_num_to_pos.read( (
char*)&e,
sizeof(e) );
133 return e.
block_id ==
id && e.block_size.value() > 0;
138 assert( block_num != 0 );
140 int64_t index_pos =
sizeof(e) * int64_t(block_num);
141 _block_num_to_pos.seekg( 0, _block_num_to_pos.end );
142 if ( _block_num_to_pos.tellg() <= index_pos )
143 FC_THROW_EXCEPTION(fc::key_not_found_exception,
"Block number ${block_num} not contained in block database", (
"block_num", block_num));
145 _block_num_to_pos.seekg( index_pos );
146 _block_num_to_pos.read( (
char*)&e,
sizeof(e) );
158 _block_num_to_pos.seekg( 0, _block_num_to_pos.end );
159 if ( _block_num_to_pos.tellg() <= index_pos )
162 _block_num_to_pos.seekg( index_pos );
163 _block_num_to_pos.read( (
char*)&e,
sizeof(e) );
167 vector<char> data( e.block_size.value() );
168 _blocks.seekg( e.block_pos.value() );
169 if (e.block_size.value())
170 _blocks.read( data.data(), e.block_size.value() );
171 auto result = fc::raw::unpack<signed_block>(data);
178 catch (
const std::exception&)
189 int64_t index_pos =
sizeof(e) * int64_t(block_num);
190 _block_num_to_pos.seekg( 0, _block_num_to_pos.end );
191 if ( _block_num_to_pos.tellg() <= index_pos )
194 _block_num_to_pos.seekg( index_pos, _block_num_to_pos.beg );
195 _block_num_to_pos.read( (
char*)&e,
sizeof(e) );
197 vector<char> data( e.block_size.value() );
198 _blocks.seekg( e.block_pos.value() );
199 _blocks.read( data.data(), e.block_size.value() );
200 auto result = fc::raw::unpack<signed_block>(data);
207 catch (
const std::exception&)
218 _block_num_to_pos.seekg( 0, _block_num_to_pos.end );
219 std::streampos pos = _block_num_to_pos.tellg();
225 _blocks.seekg( 0, _block_num_to_pos.end );
226 const std::streampos blocks_size = _blocks.tellg();
230 _block_num_to_pos.seekg( pos );
231 _block_num_to_pos.read( (
char*)&e,
sizeof(e) );
232 if( _block_num_to_pos.gcount() ==
sizeof(e) && e.block_size.value() > 0
233 && int64_t(e.block_pos.value() + e.block_size.value()) <= blocks_size )
236 vector<char> data( e.block_size.value() );
237 _blocks.seekg( e.block_pos.value() );
238 _blocks.read( data.data(), e.block_size.value() );
239 if( _blocks.gcount() == long(e.block_size.value()) )
241 const signed_block block = fc::raw::unpack<signed_block>(data);
242 if( block.
id() == e.block_id )
249 catch (
const std::exception&)
258 catch (
const std::exception&)
274 if( entry.
valid() )
return entry->block_id;
280 return (
size_t)_blocks.tellg();
285 _blocks.seekg( 0, _blocks.end );
286 return (
size_t)_blocks.tellg();
bool exists(const path &p)
optional< signed_block > fetch_by_number(uint32_t block_num) const
void pack(Stream &s, const flat_set< T, A... > &value, uint32_t _max_depth)
bool contains(const block_id_type &id) const
boost::endian::little_uint64_buf_t block_pos
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
FC_REFLECT(graphene::chain::index_entry,(block_pos)(block_size)(block_id))
size_t total_block_size() const
void create_directories(const path &p)
void open(const fc::path &dbdir)
fc::ripemd160 block_id_type
provides stack-based nullable value similar to boost::optional
optional< signed_block > last() const
boost::endian::little_uint32_buf_t block_size
void remove(const block_id_type &id)
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
block_id_type fetch_block_id(uint32_t block_num) const
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
optional< block_id_type > last_id() const
void store(const block_id_type &id, const signed_block &b)
optional< signed_block > fetch_optional(const block_id_type &id) const
wraps boost::filesystem::path to provide platform independent path manipulation.
size_t blocks_current_position() const
void resize_file(const path &file, size_t s)