Skip to content

Commit 24c2cda

Browse files
committed
Make address queries cancelable.
1 parent f3266a9 commit 24c2cda

File tree

3 files changed

+70
-48
lines changed

3 files changed

+70
-48
lines changed

include/bitcoin/database/impl/query/optional.ipp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef LIBBITCOIN_DATABASE_QUERY_OPTIONAL_IPP
2020
#define LIBBITCOIN_DATABASE_QUERY_OPTIONAL_IPP
2121

22+
#include <atomic>
2223
#include <algorithm>
2324
#include <ranges>
2425
#include <utility>
@@ -32,19 +33,19 @@ namespace database {
3233
// ----------------------------------------------------------------------------
3334
// TODO: use point keys (for multimap compression).
3435

35-
// TODO: test more.
3636
TEMPLATE
37-
bool CLASS::to_address_outputs(output_links& out,
38-
const hash_digest& key) const NOEXCEPT
37+
bool CLASS::to_address_outputs(const std::atomic_bool& cancel,
38+
output_links& out, const hash_digest& key) const NOEXCEPT
3939
{
4040
out.clear();
41+
42+
// Pushing into the vector is more efficient than precomputation of size.
4143
for (auto it = store_.address.it(key); it; ++it)
4244
{
4345
table::address::record address{};
44-
if (!store_.address.get(it, address))
46+
if (cancel || !store_.address.get(it, address))
4547
{
4648
out.clear();
47-
out.shrink_to_fit();
4849
return false;
4950
}
5051

@@ -56,11 +57,11 @@ bool CLASS::to_address_outputs(output_links& out,
5657

5758
// TODO: test more.
5859
TEMPLATE
59-
bool CLASS::to_confirmed_unspent_outputs(output_links& out,
60-
const hash_digest& key) const NOEXCEPT
60+
bool CLASS::to_confirmed_unspent_outputs(const std::atomic_bool& cancel,
61+
output_links& out, const hash_digest& key) const NOEXCEPT
6162
{
6263
output_links output_fks{};
63-
if (!to_address_outputs(output_fks, key))
64+
if (!to_address_outputs(cancel, output_fks, key))
6465
return false;
6566

6667
out.clear();
@@ -75,11 +76,11 @@ bool CLASS::to_confirmed_unspent_outputs(output_links& out,
7576

7677
// TODO: test more.
7778
TEMPLATE
78-
bool CLASS::to_minimum_unspent_outputs(output_links& out,
79-
const hash_digest& key, uint64_t minimum) const NOEXCEPT
79+
bool CLASS::to_minimum_unspent_outputs(const std::atomic_bool& cancel,
80+
output_links& out, const hash_digest& key, uint64_t minimum) const NOEXCEPT
8081
{
8182
output_links unspent_fks{};
82-
if (!to_confirmed_unspent_outputs(unspent_fks, key))
83+
if (!to_confirmed_unspent_outputs(cancel, unspent_fks, key))
8384
return false;
8485

8586
out.clear();
@@ -104,12 +105,12 @@ bool CLASS::to_minimum_unspent_outputs(output_links& out,
104105

105106
// TODO: test more.
106107
TEMPLATE
107-
bool CLASS::get_confirmed_balance(uint64_t& out,
108-
const hash_digest& key) const NOEXCEPT
108+
bool CLASS::get_confirmed_balance(const std::atomic_bool& cancel,
109+
uint64_t& out, const hash_digest& key) const NOEXCEPT
109110
{
110111
out = zero;
111112
output_links unspent_fks{};
112-
if (!to_confirmed_unspent_outputs(unspent_fks, key))
113+
if (!to_confirmed_unspent_outputs(cancel, unspent_fks, key))
113114
return false;
114115

115116
for (auto unspent_fk: unspent_fks)

include/bitcoin/database/query.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef LIBBITCOIN_DATABASE_QUERY_HPP
2020
#define LIBBITCOIN_DATABASE_QUERY_HPP
2121

22+
#include <atomic>
2223
#include <mutex>
2324
#include <utility>
2425
#include <bitcoin/system.hpp>
@@ -570,15 +571,14 @@ class query
570571
/// Optional Tables.
571572
/// -----------------------------------------------------------------------
572573

573-
/// Address, set internal to tx (natural-keyed).
574-
bool to_address_outputs(output_links& out,
575-
const hash_digest& key) const NOEXCEPT;
576-
bool to_confirmed_unspent_outputs(output_links& out,
577-
const hash_digest& key) const NOEXCEPT;
578-
bool to_minimum_unspent_outputs(output_links& out, const hash_digest& key,
579-
uint64_t value) const NOEXCEPT;
580-
bool get_confirmed_balance(uint64_t& out,
581-
const hash_digest& key) const NOEXCEPT;
574+
bool to_address_outputs(const std::atomic_bool& cancel,
575+
output_links& out, const hash_digest& key) const NOEXCEPT;
576+
bool to_confirmed_unspent_outputs(const std::atomic_bool& cancel,
577+
output_links& out, const hash_digest& key) const NOEXCEPT;
578+
bool to_minimum_unspent_outputs(const std::atomic_bool& cancel,
579+
output_links& out, const hash_digest& key, uint64_t value) const NOEXCEPT;
580+
bool get_confirmed_balance(const std::atomic_bool& cancel,
581+
uint64_t& out, const hash_digest& key) const NOEXCEPT;
582582

583583
bool is_filtered_body(const header_link& link) const NOEXCEPT;
584584
bool get_filter_body(filter& out, const header_link& link) const NOEXCEPT;

test/query/optional.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const auto events_handler = [](auto, auto) {};
2727

2828
const auto genesis_address = test::genesis.transactions_ptr()->front()->outputs_ptr()->front()->script().hash();
2929

30-
BOOST_AUTO_TEST_CASE(query_optional__get_confirmed_balance__genesis__expected)
30+
BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__genesis__expected)
3131
{
3232
settings settings{};
3333
settings.path = TEST_DIRECTORY;
@@ -36,12 +36,14 @@ BOOST_AUTO_TEST_CASE(query_optional__get_confirmed_balance__genesis__expected)
3636
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
3737
BOOST_REQUIRE(query.initialize(test::genesis));
3838

39-
uint64_t out{};
40-
BOOST_REQUIRE(query.get_confirmed_balance(out, genesis_address));
41-
BOOST_REQUIRE_EQUAL(out, 5000000000u);
39+
output_links out{};
40+
const std::atomic_bool cancel{};
41+
BOOST_REQUIRE(query.to_address_outputs(cancel, out, genesis_address));
42+
BOOST_REQUIRE_EQUAL(out.size(), 1u);
43+
BOOST_REQUIRE_EQUAL(out.front(), query.to_output(0, 0));
4244
}
4345

44-
BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__genesis__expected)
46+
BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__cancel__canceled_false)
4547
{
4648
settings settings{};
4749
settings.path = TEST_DIRECTORY;
@@ -51,9 +53,9 @@ BOOST_AUTO_TEST_CASE(query_optional__to_address_outputs__genesis__expected)
5153
BOOST_REQUIRE(query.initialize(test::genesis));
5254

5355
output_links out{};
54-
BOOST_REQUIRE(query.to_address_outputs(out, genesis_address));
55-
BOOST_REQUIRE_EQUAL(out.size(), 1u);
56-
BOOST_REQUIRE_EQUAL(out.front(), query.to_output(0, 0));
56+
const std::atomic_bool cancel{ true };
57+
BOOST_REQUIRE(!query.to_address_outputs(cancel, out, genesis_address));
58+
BOOST_REQUIRE(out.empty());
5759
}
5860

5961
BOOST_AUTO_TEST_CASE(query_optional__to_confirmed_unspent_outputs__genesis__expected)
@@ -66,24 +68,26 @@ BOOST_AUTO_TEST_CASE(query_optional__to_confirmed_unspent_outputs__genesis__expe
6668
BOOST_REQUIRE(query.initialize(test::genesis));
6769

6870
output_links out{};
69-
BOOST_REQUIRE(query.to_confirmed_unspent_outputs(out, genesis_address));
71+
const std::atomic_bool cancel{};
72+
BOOST_REQUIRE(query.to_confirmed_unspent_outputs(cancel, out, genesis_address));
7073
BOOST_REQUIRE_EQUAL(out.size(), 1u);
7174
BOOST_REQUIRE_EQUAL(out.front(), 0);
7275
}
7376

74-
////BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__above__excluded)
75-
////{
76-
//// settings settings{};
77-
//// settings.path = TEST_DIRECTORY;
78-
//// test::chunk_store store{ settings };
79-
//// test::query_accessor query{ store };
80-
//// BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
81-
//// BOOST_REQUIRE(query.initialize(test::genesis));
82-
////
83-
//// output_links out{};
84-
//// BOOST_REQUIRE(query.to_minimum_unspent_outputs(out, genesis_address, 5000000001));
85-
//// BOOST_REQUIRE(out.empty());
86-
////}
77+
BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__above__excluded)
78+
{
79+
settings settings{};
80+
settings.path = TEST_DIRECTORY;
81+
test::chunk_store store{ settings };
82+
test::query_accessor query{ store };
83+
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
84+
BOOST_REQUIRE(query.initialize(test::genesis));
85+
86+
output_links out{};
87+
const std::atomic_bool cancel{};
88+
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 5000000001));
89+
BOOST_REQUIRE(out.empty());
90+
}
8791

8892
BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__at__included)
8993
{
@@ -95,7 +99,8 @@ BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__at__included)
9599
BOOST_REQUIRE(query.initialize(test::genesis));
96100

97101
output_links out{};
98-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(out, genesis_address, 5000000000));
102+
const std::atomic_bool cancel{};
103+
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 5000000000));
99104
BOOST_REQUIRE_EQUAL(out.size(), 1u);
100105
BOOST_REQUIRE_EQUAL(out.front(), 0);
101106
}
@@ -110,14 +115,30 @@ BOOST_AUTO_TEST_CASE(query_optional__to_minimum_unspent_outputs__below__included
110115
BOOST_REQUIRE(query.initialize(test::genesis));
111116

112117
output_links out{};
113-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(out, genesis_address, 0));
118+
const std::atomic_bool cancel{};
119+
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 0));
114120
BOOST_REQUIRE_EQUAL(out.size(), 1u);
115121
BOOST_REQUIRE_EQUAL(out.front(), 0);
116-
BOOST_REQUIRE(query.to_minimum_unspent_outputs(out, genesis_address, 4999999999));
122+
BOOST_REQUIRE(query.to_minimum_unspent_outputs(cancel, out, genesis_address, 4999999999));
117123
BOOST_REQUIRE_EQUAL(out.size(), 1u);
118124
BOOST_REQUIRE_EQUAL(out.front(), 0);
119125
}
120126

127+
BOOST_AUTO_TEST_CASE(query_optional__get_confirmed_balance__genesis__expected)
128+
{
129+
settings settings{};
130+
settings.path = TEST_DIRECTORY;
131+
test::chunk_store store{ settings };
132+
test::query_accessor query{ store };
133+
BOOST_REQUIRE_EQUAL(store.create(events_handler), error::success);
134+
BOOST_REQUIRE(query.initialize(test::genesis));
135+
136+
uint64_t out{};
137+
const std::atomic_bool cancel{};
138+
BOOST_REQUIRE(query.get_confirmed_balance(cancel, out, genesis_address));
139+
BOOST_REQUIRE_EQUAL(out, 5000000000u);
140+
}
141+
121142
////BOOST_AUTO_TEST_CASE(query_optional__set_filter__get_filter_and_head__expected)
122143
////{
123144
//// const auto& filter_head0 = system::null_hash;

0 commit comments

Comments
 (0)