void hashtable_database_writer::store(const hash_digest& key_hash, size_t value_size, write_value_function write) { // Calculate the end of the last record. const uint64_t header_size = 24 + buckets_ * 8; const uint64_t records_end_offset = header_size + total_records_size_; // [ tx hash ] 32 // [ varuint value size ] // [ ... value data ... ] // [ next tx in bucket ] 8 const size_t record_size = 32 + variable_uint_size(value_size) + value_size + 8; // If a record crosses a page boundary then we align it with // the beginning of the next page. const size_t record_begin = align_if_crossing_page(page_size_, records_end_offset, record_size); BITCOIN_ASSERT(file_.size() >= record_begin + record_size); // We will insert new transactions at the beginning of the bucket's list. // I assume that more recent transactions in the blockchain are used // more often than older ones. // We lookup the existing value in the bucket first. const uint64_t bucket_index = remainder(key_hash.data(), buckets_); BITCOIN_ASSERT(bucket_index < buckets_); const uint64_t previous_bucket_value = read_bucket_value(bucket_index); // Now begin writing the record itself. uint8_t* entry = file_.data() + record_begin; auto serial = make_serializer(entry); serial.write_hash(key_hash); serial.write_variable_uint(value_size); // Call the supplied callback to serialize the data. write(serial.iterator()); serial.set_iterator(serial.iterator() + value_size); serial.write_8_bytes(previous_bucket_value); BITCOIN_ASSERT(serial.iterator() == entry + record_size); // Change file size value at file start. // This must be done first so any subsequent writes don't // overwrite this record in case of a crash or interruption. BITCOIN_ASSERT(record_begin >= header_size); const uint64_t alignment_padding = record_begin - header_size - total_records_size_; BITCOIN_ASSERT(alignment_padding <= page_size_); total_records_size_ += record_size + alignment_padding; // Now add record to bucket. const uint64_t record_begin_offset = record_begin - header_size; link_record(bucket_index, record_begin_offset); }
void write_string(const std::string& str) { write_variable_uint(str.size()); write_data(str); }