diff --git a/src/index/blockfilterindex.h b/src/index/blockfilterindex.h --- a/src/index/blockfilterindex.h +++ b/src/index/blockfilterindex.h @@ -68,4 +68,31 @@ std::vector &hashes_out) const; }; +/** + * Get a block filter index by type. Returns nullptr if index has not been + * initialized or was already destroyed. + */ +BlockFilterIndex *GetBlockFilterIndex(BlockFilterType filter_type); + +/** Iterate over all running block filter indexes, invoking fn on each. */ +void ForEachBlockFilterIndex(std::function fn); + +/** + * Initialize a block filter index for the given type if one does not already + * exist. Returns true if a new index is created and false if one has already + * been initialized. + */ +bool InitBlockFilterIndex(BlockFilterType filter_type, size_t n_cache_size, + bool f_memory = false, bool f_wipe = false); + +/** + * Destroy the block filter index with the given type. Returns false if no such + * index exists. This just releases the allocated memory and closes the database + * connection, it does not delete the index data. + */ +bool DestroyBlockFilterIndex(BlockFilterType filter_type); + +/** Destroy all open block filter indexes. */ +void DestroyAllBlockFilterIndexes(); + #endif // BITCOIN_INDEX_BLOCKFILTERINDEX_H diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp --- a/src/index/blockfilterindex.cpp +++ b/src/index/blockfilterindex.cpp @@ -99,6 +99,8 @@ }; // namespace +static std::map g_filter_indexes; + BlockFilterIndex::BlockFilterIndex(BlockFilterType filter_type, size_t n_cache_size, bool f_memory, bool f_wipe) @@ -462,3 +464,30 @@ } return true; } + +BlockFilterIndex *GetBlockFilterIndex(BlockFilterType filter_type) { + auto it = g_filter_indexes.find(filter_type); + return it != g_filter_indexes.end() ? &it->second : nullptr; +} + +void ForEachBlockFilterIndex(std::function fn) { + for (auto &entry : g_filter_indexes) { + fn(entry.second); + } +} + +bool InitBlockFilterIndex(BlockFilterType filter_type, size_t n_cache_size, + bool f_memory, bool f_wipe) { + auto result = g_filter_indexes.emplace( + std::piecewise_construct, std::forward_as_tuple(filter_type), + std::forward_as_tuple(filter_type, n_cache_size, f_memory, f_wipe)); + return result.second; +} + +bool DestroyBlockFilterIndex(BlockFilterType filter_type) { + return g_filter_indexes.erase(filter_type); +} + +void DestroyAllBlockFilterIndexes() { + g_filter_indexes.clear(); +} diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -278,4 +278,44 @@ filter_index.Stop(); } +BOOST_FIXTURE_TEST_CASE(blockfilter_index_init_destroy, BasicTestingSetup) { + BlockFilterIndex *filter_index; + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index == nullptr); + + BOOST_CHECK( + InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false)); + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index != nullptr); + BOOST_CHECK(filter_index->GetFilterType() == BlockFilterType::BASIC); + + // Initialize returns false if index already exists. + BOOST_CHECK( + !InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false)); + + int iter_count = 0; + ForEachBlockFilterIndex( + [&iter_count](BlockFilterIndex &_index) { iter_count++; }); + BOOST_CHECK_EQUAL(iter_count, 1); + + BOOST_CHECK(DestroyBlockFilterIndex(BlockFilterType::BASIC)); + + // Destroy returns false because index was already destroyed. + BOOST_CHECK(!DestroyBlockFilterIndex(BlockFilterType::BASIC)); + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index == nullptr); + + // Reinitialize index. + BOOST_CHECK( + InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false)); + + DestroyAllBlockFilterIndexes(); + + filter_index = GetBlockFilterIndex(BlockFilterType::BASIC); + BOOST_CHECK(filter_index == nullptr); +} + BOOST_AUTO_TEST_SUITE_END()