3 #include <fc/io/raw.hpp>
5 #define LOG_READ (std::ios::in | std::ios::binary)
6 #define LOG_WRITE (std::ios::out | std::ios::binary | std::ios::app)
15 optional<signed_block>
head;
83 : my(new detail::block_log_impl())
85 my->block_stream.exceptions(std::fstream::failbit | std::fstream::badbit);
86 my->index_stream.exceptions(std::fstream::failbit | std::fstream::badbit);
96 if (my->block_stream.is_open())
97 my->block_stream.close();
98 if (my->index_stream.is_open())
99 my->index_stream.close();
101 my->block_file = file;
104 my->block_stream.open(my->block_file.generic_string().c_str(),
LOG_WRITE);
105 my->index_stream.open(my->index_file.generic_string().c_str(),
LOG_WRITE);
106 my->block_write =
true;
107 my->index_write =
true;
127 auto log_size = fc::file_size(my->block_file);
128 auto index_size = fc::file_size(my->index_file);
132 ilog(
"Log is nonempty");
134 my->head_id = my->head->id();
138 my->check_block_read();
139 my->check_index_read();
141 ilog(
"Index is nonempty");
143 my->block_stream.seekg(-
sizeof(uint64_t), std::ios::end);
144 my->block_stream.read((
char*)&block_pos,
sizeof(block_pos));
147 my->index_stream.seekg(-
sizeof(uint64_t), std::ios::end);
148 my->index_stream.read((
char*)&index_pos,
sizeof(index_pos));
150 if (block_pos < index_pos)
152 ilog(
"block_pos < index_pos, close and reopen index_stream");
155 else if (block_pos > index_pos)
157 ilog(
"Index is incomplete");
163 ilog(
"Index is empty");
169 ilog(
"Index is nonempty, remove and recreate it");
170 my->index_stream.close();
172 my->index_stream.open(my->index_file.generic_string().c_str(),
LOG_WRITE);
173 my->index_write =
true;
184 return my->block_stream.is_open();
189 return fc::path(file.generic_string() +
".index");
196 my->check_block_write();
197 my->check_index_write();
199 uint64_t pos = my->block_stream.tellp();
200 FC_ASSERT((uint64_t)my->index_stream.tellp()
201 == (std::fstream::streampos)
sizeof(uint64_t) * ((uint64_t)b.
block_num() - 1),
202 "Append to index file occuring at wrong position.",
203 (
"position", (uint64_t)my->index_stream.tellp())(
"expected",
204 ((uint64_t)b.
block_num() - 1) *
sizeof(uint64_t)));
205 auto data = fc::raw::pack(b);
206 my->block_stream.write(data.data(), data.size());
207 my->block_stream.write((
char*)&pos,
sizeof(pos));
208 my->index_stream.write((
char*)&pos,
sizeof(pos));
210 my->head_id = b.
id();
219 my->block_stream.flush();
220 my->index_stream.flush();
227 my->check_block_read();
229 my->block_stream.seekg(pos);
230 std::pair<signed_block, uint64_t>
result;
231 fc::raw::unpack(my->block_stream,
result.first);
232 result.second = uint64_t(my->block_stream.tellg()) + 8;
242 optional<signed_block> b;
247 FC_ASSERT(b->block_num() == block_num,
"Wrong block was read from block log.",
248 (
"returned", b->block_num())(
"expected", block_num));
259 my->check_index_read();
263 my->index_stream.seekg(
sizeof(uint64_t) * (block_num - 1));
265 my->index_stream.read((
char*)&pos,
sizeof(pos));
275 my->check_block_read();
278 my->block_stream.seekg(-
sizeof(pos), std::ios::end);
279 my->block_stream.read((
char*)&pos,
sizeof(pos));
290 void block_log::construct_index()
294 ilog(
"Reconstructing Block Log Index...");
295 my->index_stream.close();
297 my->index_stream.open(my->index_file.generic_string().c_str(),
LOG_WRITE);
298 my->index_write =
true;
302 my->check_block_read();
304 my->block_stream.seekg(-
sizeof(uint64_t), std::ios::end);
305 my->block_stream.read((
char*)&end_pos,
sizeof(end_pos));
308 my->block_stream.seekg(pos);
310 while (pos < end_pos)
312 fc::raw::unpack(my->block_stream, tmp);
313 my->block_stream.read((
char*)&pos,
sizeof(pos));
314 my->index_stream.write((
char*)&pos,
sizeof(pos));
uint64_t append(const signed_block &b)
const optional< signed_block > & head() const
static const uint64_t npos
optional< signed_block > read_block_by_num(uint32_t block_num) const
static fc::path block_log_index_path(const fc::path &block_log_file)
void open(const fc::path &file)
signed_block read_head() const
uint64_t get_block_pos(uint32_t block_num) const
std::pair< signed_block, uint64_t > read_block(uint64_t file_pos) const
std::fstream block_stream
std::fstream index_stream
optional< signed_block > head
void remove_all(db_index &db_idx, utils::bidir_range< const TObject > items)
fc::ripemd160 block_id_type