| 898 | } |
| 899 | |
| 900 | void BlockChain::start_internal_import() { |
| 901 | m_log(logging::INFO) << "Blockchain database has old format, preparing for internal block import..."; |
| 902 | if (m_internal_import_chain.empty()) { |
| 903 | const std::vector<std::string> former_prefixes{ |
| 904 | TIP_CHAIN_PREFIX + "B/", TIP_CHAIN_PREFIX + "1/", TIP_CHAIN_PREFIX + "/", TIP_CHAIN_PREFIX}; |
| 905 | for (auto &&prefix : former_prefixes) { |
| 906 | std::vector<Hash> main_chain; |
| 907 | for (Height ha = 0;; ha += 1) { |
| 908 | BinaryArray ba; |
| 909 | if (!m_db.get(prefix + common::write_varint_sqlite4(ha), ba)) |
| 910 | break; |
| 911 | Hash bid; |
| 912 | seria::from_binary(bid, ba); |
| 913 | main_chain.push_back(bid); |
| 914 | } |
| 915 | if (main_chain.size() > m_internal_import_chain.size()) |
| 916 | m_internal_import_chain = main_chain; |
| 917 | } |
| 918 | } |
| 919 | // we could wish to advance version on half-imported chain |
| 920 | std::set<Hash> main_chain_bids{m_internal_import_chain.begin(), m_internal_import_chain.end()}; |
| 921 | m_log(logging::INFO) << "Found " << m_internal_import_chain.size() << " blocks from main chain"; |
| 922 | size_t erased = 0, skipped = 0; |
| 923 | const size_t total_items = m_db.get_approximate_items_count(); |
| 924 | const std::string total_items_str = (total_items == std::numeric_limits<size_t>::max()) |
| 925 | ? "unknown" |
| 926 | : common::to_string((total_items + 999999) / 1000000); |
| 927 | for (DB::Cursor cur = m_db.rbegin(std::string{}); !cur.end();) { |
| 928 | if ((erased + skipped) % 1000000 == 0) |
| 929 | m_log(logging::INFO) << "Processing " << (erased + skipped) / 1000000 << "/" << total_items_str |
| 930 | << " million DB records"; |
| 931 | if (cur.get_suffix().find(BLOCK_PREFIX) == 0 && |
| 932 | cur.get_suffix().substr(cur.get_suffix().size() - BLOCK_SUFFIX.size()) == BLOCK_SUFFIX) { |
| 933 | Hash bid; |
| 934 | DB::from_binary_key(cur.get_suffix(), BLOCK_PREFIX.size(), bid.data, sizeof(bid.data)); |
| 935 | if (main_chain_bids.count(bid) != 0) { |
| 936 | cur.next(); |
| 937 | skipped += 1; |
| 938 | continue; // block in main chain |
| 939 | } |
| 940 | BinaryArray block_data; |
| 941 | if (get_block(bid, &block_data, nullptr)) |
| 942 | m_archive.add(Archive::BLOCK, block_data, bid, "start_internal_import"); |
| 943 | } |
| 944 | cur.erase(); |
| 945 | erased += 1; |
| 946 | } |
| 947 | m_db.put("internal_import_chain", seria::to_binary(m_internal_import_chain), true); // we've just erased it :) |
| 948 | m_log(logging::INFO) << "Deleted " << erased << " records, skipped " << skipped << " records"; |
| 949 | } |
| 950 | |
| 951 | bool BlockChain::internal_import() { |
| 952 | auto idea_start = std::chrono::high_resolution_clock::now(); |
nothing calls this directly
no test coverage detected