Skip to content

Commit d62bb47

Browse files
authored
Merge pull request #573 from evoskuil/master
Add arraymap.reset(), remove dead code, arraymap index guard.
2 parents 6b5e24a + 02910ee commit d62bb47

12 files changed

Lines changed: 151 additions & 245 deletions

File tree

include/bitcoin/database/impl/primitives/arrayhead.ipp

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ CLASS::arrayhead(storage& head, const Link& buckets) NOEXCEPT
3333
}
3434

3535
TEMPLATE
36-
size_t CLASS::size() const NOEXCEPT
36+
inline size_t CLASS::size() const NOEXCEPT
3737
{
3838
return file_.size();
3939
}
4040

4141
TEMPLATE
42-
size_t CLASS::buckets() const NOEXCEPT
42+
inline size_t CLASS::buckets() const NOEXCEPT
4343
{
4444
const auto count = position_to_link(size()).value;
4545
BC_ASSERT(count < Link::terminal);
@@ -55,8 +55,9 @@ bool CLASS::enabled() const NOEXCEPT
5555
TEMPLATE
5656
inline Link CLASS::index(size_t key) const NOEXCEPT
5757
{
58-
if (key >= buckets())
59-
return {};
58+
// buckets a table lock via file.size().
59+
////if (key >= buckets()) return {};
60+
////BC_ASSERT_MSG(key < buckets(), "index overflow");
6061

6162
// Put index does not validate, allowing for head expansion.
6263
return putter_index(key);
@@ -70,28 +71,32 @@ inline Link CLASS::putter_index(size_t key) const NOEXCEPT
7071
}
7172

7273
TEMPLATE
73-
bool CLASS::create() NOEXCEPT
74+
bool CLASS::clear() NOEXCEPT
7475
{
75-
if (is_nonzero(file_.size()))
76+
const auto ptr = file_.get();
77+
if (!ptr)
7678
return false;
7779

78-
const auto allocation = link_to_position(initial_buckets_);
79-
const auto start = file_.allocate(allocation);
80+
// Retains head size, since head is array not map, and resets body logical
81+
// count to zero, which is picked up in arraymap::reset(). Body file size
82+
// remains unchanged and subject to initialization size at each startup. So
83+
// there is no reduction until restart, which can include config change.
84+
std::fill_n(ptr->data(), size(), system::bit_all<uint8_t>);
85+
return set_body_count(zero);
86+
}
8087

81-
// Guards addition overflow in manager_.get (start must be valid).
82-
if (start == storage::eof)
88+
TEMPLATE
89+
bool CLASS::create() NOEXCEPT
90+
{
91+
if (is_nonzero(size()))
8392
return false;
8493

85-
const auto ptr = file_.get(start);
86-
if (!ptr)
94+
// Guards addition overflow in manager_.get (start must be valid).
95+
if (file_.allocate(link_to_position(initial_buckets_)) == storage::eof)
8796
return false;
8897

89-
BC_ASSERT_MSG(verify(), "unexpected body size");
90-
91-
// std::memset/fill_n have identical performance (on win32).
92-
////std::memset(ptr->data(), system::bit_all<uint8_t>, size());
93-
std::fill_n(ptr->data(), size(), system::bit_all<uint8_t>);
94-
return set_body_count(zero);
98+
BC_ASSERT_MSG(verify(), "unexpected head size");
99+
return clear();
95100
}
96101

97102
TEMPLATE
@@ -104,7 +109,7 @@ TEMPLATE
104109
bool CLASS::get_body_count(Link& count) const NOEXCEPT
105110
{
106111
const auto ptr = file_.get();
107-
if (!ptr || Link::size > file_.size())
112+
if (!ptr || Link::size > size())
108113
return false;
109114

110115
count = array_cast<Link::size>(ptr->data());
@@ -115,7 +120,7 @@ TEMPLATE
115120
bool CLASS::set_body_count(const Link& count) NOEXCEPT
116121
{
117122
const auto ptr = file_.get();
118-
if (!ptr || Link::size > file_.size())
123+
if (!ptr || Link::size > size())
119124
return false;
120125

121126
array_cast<Link::size>(ptr->data()) = count;

include/bitcoin/database/impl/primitives/arraymap.ipp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ bool CLASS::close() NOEXCEPT
4949
return head_.set_body_count(body_.count());
5050
}
5151

52+
TEMPLATE
53+
bool CLASS::reset() NOEXCEPT
54+
{
55+
Link count{};
56+
return head_.clear() && head_.get_body_count(count) &&
57+
body_.truncate(count);
58+
}
59+
5260
TEMPLATE
5361
bool CLASS::backup() NOEXCEPT
5462
{
@@ -128,12 +136,6 @@ code CLASS::reload() NOEXCEPT
128136
// query interface
129137
// ----------------------------------------------------------------------------
130138

131-
TEMPLATE
132-
inline bool CLASS::exists(size_t key) const NOEXCEPT
133-
{
134-
return !at(key).is_terminal();
135-
}
136-
137139
TEMPLATE
138140
inline Link CLASS::at(size_t key) const NOEXCEPT
139141
{

include/bitcoin/database/impl/primitives/hashhead.ipp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ CLASS::hashhead(storage& head, const Link& buckets) NOEXCEPT
3636
}
3737

3838
TEMPLATE
39-
size_t CLASS::size() const NOEXCEPT
39+
inline size_t CLASS::size() const NOEXCEPT
4040
{
4141
return link_to_position(buckets_);
4242
}
4343

4444
TEMPLATE
45-
size_t CLASS::buckets() const NOEXCEPT
45+
inline size_t CLASS::buckets() const NOEXCEPT
4646
{
4747
return buckets_;
4848
}
@@ -64,7 +64,7 @@ bool CLASS::create() NOEXCEPT
6464
if (!ptr)
6565
return false;
6666

67-
BC_ASSERT_MSG(verify(), "unexpected body size");
67+
BC_ASSERT_MSG(verify(), "unexpected head size");
6868

6969
// std::memset/fill_n have identical performance (on win32).
7070
////std::memset(ptr->data(), system::bit_all<uint8_t>, allocation);
@@ -105,20 +105,11 @@ inline Link CLASS::index(const Key& key) const NOEXCEPT
105105
{
106106
BC_ASSERT_MSG(is_nonzero(buckets_), "hash table requires buckets");
107107

108-
// TODO: for greater flexibility, inject hash function through template.
109-
if constexpr (Hash)
110-
{
111-
// djb2_hash exhibits very poor uniqueness result for sequential keys.
112-
return system::djb2_hash(key) % buckets_;
113-
}
114-
else
115-
{
116-
// unique_hash assumes sufficient uniqueness in low order key bytes.
117-
return system::unique_hash(key) % buckets_;
118-
119-
// TODO: restrict buckets to power of two and replace modulo above with
120-
// return and(sub1(buckets), unique_hash(key)) [and() is much faster].
121-
}
108+
// unique_hash assumes sufficient uniqueness in low order key bytes.
109+
return system::unique_hash(key) % buckets_;
110+
111+
// TODO: restrict buckets to power of two and replace modulo above with
112+
// return and(sub1(buckets), unique_hash(key)) [and() is much faster].
122113
}
123114

124115
TEMPLATE

include/bitcoin/database/primitives/arrayhead.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,26 @@ class arrayhead
4141
arrayhead(storage& head, const Link& buckets) NOEXCEPT;
4242

4343
/// Sizing is dynamic (thread safe).
44-
size_t size() const NOEXCEPT;
45-
size_t buckets() const NOEXCEPT;
44+
inline size_t size() const NOEXCEPT;
45+
inline size_t buckets() const NOEXCEPT;
4646

4747
/// Configure initial buckets to zero to disable the table.
4848
bool enabled() const NOEXCEPT;
4949

5050
/// Create from empty head file (not thread safe).
5151
bool create() NOEXCEPT;
5252

53+
/// Clear the existing index of all links.
54+
bool clear() NOEXCEPT;
55+
5356
/// False if head file size incorrect (not thread safe).
5457
bool verify() const NOEXCEPT;
5558

5659
/// Unsafe if verify false (not thread safe).
5760
bool get_body_count(Link& count) const NOEXCEPT;
5861
bool set_body_count(const Link& count) NOEXCEPT;
5962

60-
/// Convert natural key to head bucket index (validated).
63+
/// Convert natural key to head bucket index (unvalidated).
6164
inline Link index(size_t key) const NOEXCEPT;
6265

6366
/// Convert natural key to head bucket index (unvalidated).

include/bitcoin/database/primitives/arraymap.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class arraymap
5050

5151
bool create() NOEXCEPT;
5252
bool close() NOEXCEPT;
53+
bool reset() NOEXCEPT;
5354
bool backup() NOEXCEPT;
5455
bool restore() NOEXCEPT;
5556
bool verify() const NOEXCEPT;
@@ -87,13 +88,10 @@ class arraymap
8788
/// Query interface, iterator is not thread safe.
8889
/// -----------------------------------------------------------------------
8990

90-
/// True if an instance of object with key exists.
91-
inline bool exists(size_t key) const NOEXCEPT;
92-
93-
/// Return element link at key or terminal if not found/error.
91+
/// Return element link at key, terminal if not found/error (unverified).
9492
inline Link at(size_t key) const NOEXCEPT;
9593

96-
/// Get first element matching the search key, false if not found/error.
94+
/// Get first element matching key, false if not found/error (unverified).
9795
template <typename Element, if_equal<Element::size, Size> = true>
9896
inline bool at(size_t key, Element& element) const NOEXCEPT;
9997

include/bitcoin/database/primitives/hashhead.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
namespace libbitcoin {
2828
namespace database {
2929

30-
template <typename Link, typename Key, bool Hash>
30+
template <typename Link, typename Key>
3131
class hashhead
3232
{
3333
public:
@@ -39,8 +39,8 @@ class hashhead
3939
hashhead(storage& head, const Link& buckets) NOEXCEPT;
4040

4141
/// Sizing (thread safe).
42-
size_t size() const NOEXCEPT;
43-
size_t buckets() const NOEXCEPT;
42+
inline size_t size() const NOEXCEPT;
43+
inline size_t buckets() const NOEXCEPT;
4444

4545
/// Create from empty head file (not thread safe).
4646
bool create() NOEXCEPT;
@@ -86,8 +86,8 @@ class hashhead
8686
} // namespace database
8787
} // namespace libbitcoin
8888

89-
#define TEMPLATE template <typename Link, typename Key, bool Hash>
90-
#define CLASS hashhead<Link, Key, Hash>
89+
#define TEMPLATE template <typename Link, typename Key>
90+
#define CLASS hashhead<Link, Key>
9191

9292
#include <bitcoin/database/impl/primitives/hashhead.ipp>
9393

include/bitcoin/database/primitives/hashmap.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace database {
3535
/// Readers and writers are always prepositioned at data, and are limited to
3636
/// the extent the record/slab size is known (limit can always be removed).
3737
/// Streams are always initialized from first element byte up to file limit.
38-
template <typename Link, typename Key, size_t Size, bool Hash>
38+
template <typename Link, typename Key, size_t Size>
3939
class hashmap
4040
{
4141
public:
@@ -196,7 +196,7 @@ class hashmap
196196
static constexpr auto key_size = array_count<Key>;
197197
static constexpr auto index_size = Link::size + key_size;
198198

199-
using head = database::hashhead<Link, Key, Hash>;
199+
using head = database::hashhead<Link, Key>;
200200
using body = database::manager<Link, Key, Size>;
201201

202202
// Thread safe (index/top/push).
@@ -209,13 +209,13 @@ class hashmap
209209

210210
template <typename Element>
211211
using hash_map = hashmap<linkage<Element::pk>, system::data_array<Element::sk>,
212-
Element::size, Element::hash_function>;
212+
Element::size>;
213213

214214
} // namespace database
215215
} // namespace libbitcoin
216216

217-
#define TEMPLATE template <typename Link, typename Key, size_t Size, bool Hash>
218-
#define CLASS hashmap<Link, Key, Size, Hash>
217+
#define TEMPLATE template <typename Link, typename Key, size_t Size>
218+
#define CLASS hashmap<Link, Key, Size>
219219

220220
#include <bitcoin/database/impl/primitives/hashmap.ipp>
221221

include/bitcoin/database/tables/schema.hpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ namespace schema
133133
// record hashmap
134134
struct header
135135
{
136-
static constexpr bool hash_function = false;
137136
static constexpr size_t pk = schema::block;
138137
static constexpr size_t sk = schema::hash;
139138
static constexpr size_t minsize =
@@ -157,7 +156,6 @@ namespace schema
157156
// record hashmap
158157
struct transaction
159158
{
160-
static constexpr bool hash_function = false;
161159
static constexpr size_t pk = schema::tx;
162160
static constexpr size_t sk = schema::hash;
163161
static constexpr size_t minsize =
@@ -209,7 +207,6 @@ namespace schema
209207
// record multimap
210208
struct point
211209
{
212-
static constexpr bool hash_function = false;
213210
static constexpr size_t pk = schema::ins_;
214211
static constexpr size_t sk = schema::hash + schema::index;
215212
static constexpr size_t minsize = zero;
@@ -252,7 +249,6 @@ namespace schema
252249
// slab hashmap
253250
struct txs
254251
{
255-
static constexpr bool hash_function = false;
256252
static constexpr size_t pk = schema::txs_;
257253
static constexpr size_t sk = schema::header::pk;
258254
static constexpr size_t minsize =
@@ -286,7 +282,6 @@ namespace schema
286282
// address record count is output count.
287283
struct address
288284
{
289-
static constexpr bool hash_function = false;
290285
static constexpr size_t pk = schema::outs_;
291286
static constexpr size_t sk = schema::hash;
292287
static constexpr size_t minsize = schema::put;
@@ -300,7 +295,6 @@ namespace schema
300295
// record hashmap
301296
struct strong_tx
302297
{
303-
static constexpr bool hash_function = false;
304298
static constexpr size_t pk = schema::tx;
305299
static constexpr size_t sk = schema::transaction::pk;
306300
static constexpr size_t minsize =
@@ -333,7 +327,6 @@ namespace schema
333327
// slab hashmap
334328
struct validated_bk
335329
{
336-
static constexpr bool hash_function = false;
337330
static constexpr size_t pk = schema::bk_slab;
338331
static constexpr size_t sk = schema::header::pk;
339332
static constexpr size_t minsize =
@@ -348,7 +341,6 @@ namespace schema
348341
// slab modest (sk:4) multimap, with low multiple rate.
349342
struct validated_tx
350343
{
351-
static constexpr bool hash_function = false;
352344
static constexpr size_t pk = schema::tx_slab;
353345
static constexpr size_t sk = schema::transaction::pk;
354346
static constexpr size_t minsize =
@@ -368,7 +360,6 @@ namespace schema
368360
// slab hashmap
369361
struct neutrino
370362
{
371-
static constexpr bool hash_function = false;
372363
static constexpr size_t pk = schema::neutrino_;
373364
static constexpr size_t sk = schema::header::pk;
374365
static constexpr size_t minsize =

test/primitives/arrayhead.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(arrayhead__get_body_count__created__zero)
8888
BOOST_REQUIRE_EQUAL(count, zero);
8989
}
9090

91-
BOOST_AUTO_TEST_CASE(arrayhead__set_body_count__get__expected)
91+
BOOST_AUTO_TEST_CASE(arrayhead__set_body_count__get_body_count__expected)
9292
{
9393
data_chunk data;
9494
test::chunk_storage store{ data };
@@ -103,6 +103,25 @@ BOOST_AUTO_TEST_CASE(arrayhead__set_body_count__get__expected)
103103
BOOST_REQUIRE_EQUAL(count, expected);
104104
}
105105

106+
BOOST_AUTO_TEST_CASE(arrayhead__clear__get_body_count__zero)
107+
{
108+
data_chunk data;
109+
test::chunk_storage store{ data };
110+
test_header head{ store, buckets };
111+
BOOST_REQUIRE(head.create());
112+
113+
constexpr auto expected = 42u;
114+
BOOST_REQUIRE(head.set_body_count(expected));
115+
116+
link count{};
117+
BOOST_REQUIRE(head.get_body_count(count));
118+
BOOST_REQUIRE_EQUAL(count, expected);
119+
120+
BOOST_REQUIRE(head.clear());
121+
BOOST_REQUIRE(head.get_body_count(count));
122+
BOOST_REQUIRE_EQUAL(count, zero);
123+
}
124+
106125
BOOST_AUTO_TEST_CASE(arrayhead__at__key__terminal)
107126
{
108127
test::chunk_storage store;

0 commit comments

Comments
 (0)