Skip to content

Commit 87158c5

Browse files
committed
Add overrides to hashmap, write key in unlinked tx.set.
1 parent 4e422e1 commit 87158c5

8 files changed

Lines changed: 98 additions & 39 deletions

File tree

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

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,28 @@ inline Link CLASS::top(const Link& link) const NOEXCEPT
143143
return head_.top(link);
144144
}
145145

146+
TEMPLATE
147+
inline bool CLASS::exists(const memory_ptr& ptr, const Key& key) const NOEXCEPT
148+
{
149+
return !first(ptr, key).is_terminal();
150+
}
151+
146152
TEMPLATE
147153
inline bool CLASS::exists(const Key& key) const NOEXCEPT
148154
{
149155
return !first(key).is_terminal();
150156
}
151157

158+
TEMPLATE
159+
inline Link CLASS::first(const memory_ptr& ptr, const Key& key) const NOEXCEPT
160+
{
161+
return first(ptr, head_.top(key), key);
162+
}
163+
152164
TEMPLATE
153165
inline Link CLASS::first(const Key& key) const NOEXCEPT
154166
{
155-
return first(get_memory(), head_.top(key), key);
167+
return first(get_memory(), key);
156168
}
157169

158170
TEMPLATE
@@ -250,14 +262,32 @@ inline bool CLASS::get(const iterator& it, const Link& link,
250262

251263
TEMPLATE
252264
template <typename Element, if_equal<Element::size, Size>>
253-
bool CLASS::set(const Link& link, const Element& element) NOEXCEPT
265+
bool CLASS::set(const memory_ptr& ptr, const Link& link, const Key& key,
266+
const Element& element) NOEXCEPT
254267
{
255268
using namespace system;
256-
const auto ptr = body_.get(link);
257269
if (!ptr)
258270
return false;
259271

260-
iostream stream{ *ptr };
272+
const auto start = body::link_to_position(link);
273+
if (is_limited<ptrdiff_t>(start))
274+
return false;
275+
276+
const auto size = ptr->size();
277+
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
278+
if (position > size)
279+
return false;
280+
281+
// Stream starts at record and the index is skipped for reader convenience.
282+
const auto offset = ptr->offset(start);
283+
if (is_null(offset))
284+
return false;
285+
286+
// Set element search key.
287+
unsafe_array_cast<uint8_t, key_size>(std::next(offset,
288+
Link::size)) = key;
289+
290+
iostream stream{ offset, size - position };
261291
finalizer sink{ stream };
262292
sink.skip_bytes(index_size);
263293

@@ -267,21 +297,30 @@ bool CLASS::set(const Link& link, const Element& element) NOEXCEPT
267297

268298
TEMPLATE
269299
template <typename Element, if_equal<Element::size, Size>>
270-
inline Link CLASS::set_link(const Element& element) NOEXCEPT
300+
bool CLASS::set(const Link& link, const Key& key,
301+
const Element& element) NOEXCEPT
302+
{
303+
return set(get_memory(), link, key, element);
304+
}
305+
306+
TEMPLATE
307+
template <typename Element, if_equal<Element::size, Size>>
308+
inline Link CLASS::set_link(const Key& key, const Element& element) NOEXCEPT
271309
{
272310
Link link{};
273-
if (!set_link(link, element))
311+
if (!set_link(link, key, element))
274312
return {};
275313

276314
return link;
277315
}
278316

279317
TEMPLATE
280318
template <typename Element, if_equal<Element::size, Size>>
281-
inline bool CLASS::set_link(Link& link, const Element& element) NOEXCEPT
319+
inline bool CLASS::set_link(Link& link, const Key& key,
320+
const Element& element) NOEXCEPT
282321
{
283322
link = allocate(element.count());
284-
return set(link, element);
323+
return set(link, key, element);
285324
}
286325

287326
TEMPLATE
@@ -329,22 +368,33 @@ inline bool CLASS::put(const memory_ptr& ptr, const Link& link, const Key& key,
329368
}
330369

331370
TEMPLATE
332-
bool CLASS::commit(const Link& link, const Key& key) NOEXCEPT
371+
bool CLASS::commit(const memory_ptr& ptr, const Link& link,
372+
const Key& key) NOEXCEPT
333373
{
334374
using namespace system;
335-
const auto ptr = body_.get(link);
336375
if (!ptr)
337376
return false;
338377

339-
// Set element search key.
340-
unsafe_array_cast<uint8_t, key_size>(std::next(ptr->begin(),
341-
Link::size)) = key;
378+
// get element offset (fault)
379+
const auto offset = ptr->offset(body::link_to_position(link));
380+
if (is_null(offset))
381+
return false;
382+
383+
//// Set element search key.
384+
//unsafe_array_cast<uint8_t, key_size>(std::next(offset,
385+
// Link::size)) = key;
342386

343387
// Commit element to search index (terminal is a valid bucket index).
344-
auto& next = unsafe_array_cast<uint8_t, Link::size>(ptr->begin());
388+
auto& next = unsafe_array_cast<uint8_t, Link::size>(offset);
345389
return head_.push(link, next, head_.index(key));
346390
}
347391

392+
TEMPLATE
393+
bool CLASS::commit(const Link& link, const Key& key) NOEXCEPT
394+
{
395+
return commit(get_memory(), link, key);
396+
}
397+
348398
TEMPLATE
349399
inline Link CLASS::commit_link(const Link& link, const Key& key) NOEXCEPT
350400
{

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ code CLASS::set_code(tx_link& tx_fk, const transaction& tx) NOEXCEPT
127127

128128
// Create tx record.
129129
// Commit is deferred for point/address index consistency.
130-
if (!store_.tx.set(tx_fk, table::transaction::record_put_ref
130+
if (!store_.tx.set(tx_fk, tx.get_hash(false), table::transaction::put_ref
131131
{
132132
{},
133133
tx,
@@ -232,7 +232,7 @@ code CLASS::set_code(header_link& out_fk, const header& header,
232232
const auto scope = store_.get_transactor();
233233

234234
// Clean single allocation failure (e.g. disk full).
235-
out_fk = store_.header.put_link(key, table::header::record_put_ref
235+
out_fk = store_.header.put_link(key, table::header::put_ref
236236
{
237237
{},
238238
ctx,

include/bitcoin/database/primitives/hashmap.hpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,11 @@ class hashmap
9696
inline Link top(const Link& list) const NOEXCEPT;
9797

9898
/// True if an instance of object with key exists.
99+
inline bool exists(const memory_ptr& ptr, const Key& key) const NOEXCEPT;
99100
inline bool exists(const Key& key) const NOEXCEPT;
100101

101102
/// Return first element link or terminal if not found/error.
103+
inline Link first(const memory_ptr& ptr, const Key& key) const NOEXCEPT;
102104
inline Link first(const Key& key) const NOEXCEPT;
103105

104106
/// Iterator holds shared lock on storage remap.
@@ -143,13 +145,19 @@ class hashmap
143145

144146
/// Set element into previously allocated link (follow with commit).
145147
template <typename Element, if_equal<Element::size, Size> = true>
146-
bool set(const Link& link, const Element& element) NOEXCEPT;
148+
bool set(const memory_ptr& ptr, const Link& link, const Key& key,
149+
const Element& element) NOEXCEPT;
150+
151+
/// Set element into previously allocated link (follow with commit).
152+
template <typename Element, if_equal<Element::size, Size> = true>
153+
bool set(const Link& link, const Key& key, const Element& element) NOEXCEPT;
147154

148155
/// Allocate and set element, and return link (follow with commit).
149156
template <typename Element, if_equal<Element::size, Size> = true>
150-
inline Link set_link(const Element& element) NOEXCEPT;
157+
inline Link set_link(const Key& key, const Element& element) NOEXCEPT;
151158
template <typename Element, if_equal<Element::size, Size> = true>
152-
inline bool set_link(Link& link, const Element& element) NOEXCEPT;
159+
inline bool set_link(Link& link, const Key& key,
160+
const Element& element) NOEXCEPT;
153161

154162
/// Allocate, set, commit element to key, and return link.
155163
template <typename Element, if_equal<Element::size, Size> = true>
@@ -173,6 +181,7 @@ class hashmap
173181
const Element& element) NOEXCEPT;
174182

175183
/// Commit previously set element at link to key.
184+
bool commit(const memory_ptr& ptr, const Link& link, const Key& key) NOEXCEPT;
176185
bool commit(const Link& link, const Key& key) NOEXCEPT;
177186
inline Link commit_link(const Link& link, const Key& key) NOEXCEPT;
178187

include/bitcoin/database/tables/archives/header.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ struct header
116116
////};
117117

118118
// This is redundant with record_put_ptr except this does not capture.
119-
struct record_put_ref
119+
struct put_ref
120120
: public schema::header
121121
{
122122
// header.previous_block_hash() ignored.

include/bitcoin/database/tables/archives/transaction.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ struct transaction
137137
outs::integer outs_fk{};
138138
};
139139

140-
struct record_put_ref
140+
struct put_ref
141141
: public schema::transaction
142142
{
143143
inline bool to_data(finalizer& sink) const NOEXCEPT

test/primitives/hashmap.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -876,15 +876,15 @@ BOOST_AUTO_TEST_CASE(hashmap__set_commit__record__expected)
876876
hashmap_<link5, key10, flex_record::size> instance{ head_store, body_store, 2 };
877877
BOOST_REQUIRE(instance.create());
878878

879+
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
879880
constexpr auto size = link5::size + array_count<key10> + flex_record::size;
880-
const auto link = instance.set_link(flex_record{ 0x01020304_u32 });
881+
const auto link = instance.set_link(key1, flex_record{ 0x01020304_u32 });
881882
BOOST_REQUIRE(!link.is_terminal());
882883
BOOST_REQUIRE_EQUAL(link, 0u);
883884
BOOST_REQUIRE_EQUAL(body_store.buffer().size(), size);
884885
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffffffffffffffffffffffffffffffffff"));
885-
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000000000000000000000004030201"));
886+
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000102030405060708090a04030201"));
886887

887-
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
888888
BOOST_REQUIRE(instance.commit(link, key1));
889889
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffff0000000000ffffffffffffffffffff"));
890890
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("ffffffffff0102030405060708090a04030201"));
@@ -899,16 +899,16 @@ BOOST_AUTO_TEST_CASE(hashmap__allocate_set_commit__record__expected)
899899
hashmap_<link5, key10, flex_record::size> instance{ head_store, body_store, 2 };
900900
BOOST_REQUIRE(instance.create());
901901

902+
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
902903
constexpr auto size = link5::size + array_count<key10> + flex_record::size;
903904
const auto link = instance.allocate(1);
904905
BOOST_REQUIRE_EQUAL(link, 0u);
905906
BOOST_REQUIRE_EQUAL(body_store.buffer().size(), size);
906907

907-
BOOST_REQUIRE(instance.set(link, flex_record{ 0x01020304_u32 }));
908+
BOOST_REQUIRE(instance.set(link, key1, flex_record{ 0x01020304_u32 }));
908909
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffffffffffffffffffffffffffffffffff"));
909-
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000000000000000000000004030201"));
910+
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000102030405060708090a04030201"));
910911

911-
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
912912
BOOST_REQUIRE(instance.commit(link, key1));
913913
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffff0000000000ffffffffffffffffffff"));
914914
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("ffffffffff0102030405060708090a04030201"));
@@ -921,13 +921,13 @@ BOOST_AUTO_TEST_CASE(hashmap__allocate_put1__record__expected)
921921
test::chunk_storage body_store{};
922922
hashmap_<link5, key10, flex_record::size> instance{ head_store, body_store, 2 };
923923
BOOST_REQUIRE(instance.create());
924-
924+
925+
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
925926
constexpr auto size = link5::size + array_count<key10> + sizeof(uint32_t);
926927
const auto link = instance.allocate(1);
927928
BOOST_REQUIRE_EQUAL(link, 0u);
928929
BOOST_REQUIRE_EQUAL(body_store.buffer().size(), size);
929930

930-
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
931931
BOOST_REQUIRE(instance.put(link, key1, flex_record{ 0x01020304_u32 }));
932932
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffff0000000000ffffffffffffffffffff"));
933933
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("ffffffffff0102030405060708090a04030201"));
@@ -955,16 +955,16 @@ BOOST_AUTO_TEST_CASE(hashmap__set_commit_link__slab__expected)
955955
hashmap_<link5, key10, flex_slab::size> instance{ head_store, body_store, 2 };
956956
BOOST_REQUIRE(instance.create());
957957

958+
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
958959
constexpr auto size = link5::size + array_count<key10> + sizeof(uint32_t);
959960
link5 link{};
960-
BOOST_REQUIRE(instance.set_link(link, flex_slab{ 0x01020304_u32 }));
961+
BOOST_REQUIRE(instance.set_link(link, key1, flex_slab{ 0x01020304_u32 }));
961962
BOOST_REQUIRE(!link.is_terminal());
962963
BOOST_REQUIRE_EQUAL(link, 0u);
963964
BOOST_REQUIRE_EQUAL(body_store.buffer().size(), size);
964965
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffffffffffffffffffffffffffffffffff"));
965-
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000000000000000000000004030201"));
966+
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000102030405060708090a04030201"));
966967

967-
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
968968
BOOST_REQUIRE(!instance.commit_link(link, key1).is_terminal());
969969
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffff0000000000ffffffffffffffffffff"));
970970
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("ffffffffff0102030405060708090a04030201"));
@@ -978,16 +978,16 @@ BOOST_AUTO_TEST_CASE(hashmap__allocate_set_commit__slab__expected)
978978
hashmap_<link5, key10, flex_slab::size> instance{ head_store, body_store, 2 };
979979
BOOST_REQUIRE(instance.create());
980980

981+
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
981982
constexpr auto size = link5::size + array_count<key10> + sizeof(uint32_t);
982983
const auto link = instance.allocate(size);
983984
BOOST_REQUIRE_EQUAL(link, 0u);
984985
BOOST_REQUIRE_EQUAL(body_store.buffer().size(), size);
985986

986-
BOOST_REQUIRE(instance.set(link, flex_slab{ 0x01020304_u32 }));
987+
BOOST_REQUIRE(instance.set(link, key1, flex_slab{ 0x01020304_u32 }));
987988
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffffffffffffffffffffffffffffffffff"));
988-
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000000000000000000000004030201"));
989+
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("00000000000102030405060708090a04030201"));
989990

990-
constexpr key10 key1{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a };
991991
BOOST_REQUIRE(instance.commit(link, key1));
992992
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("0000000000ffffffffff0000000000ffffffffffffffffffff"));
993993
BOOST_REQUIRE_EQUAL(body_store.buffer(), base16_chunk("ffffffffff0102030405060708090a04030201"));

test/tables/archives/header.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(header__put_ref__get__expected)
152152
BOOST_REQUIRE(instance.create());
153153
BOOST_REQUIRE(!instance.put_link({}, table::header::record{}).is_terminal());
154154

155-
const table::header::record_put_ref put_ref
155+
const table::header::put_ref put_ref
156156
{
157157
{},
158158
expected.ctx,

test/tables/caches/prevout.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@
273273
//// BOOST_REQUIRE_EQUAL(element.output_tx_fk(), expected_tx);
274274
////}
275275
////
276-
////// record_put_ref
276+
////// put_ref
277277
////
278278
////BOOST_AUTO_TEST_CASE(prevout__put_ref__get_non_empty_block_with_default_metadata__inside_spend_terminals)
279279
////{
@@ -284,7 +284,7 @@
284284
//// table::prevout instance{ head_store, body_store, 5 };
285285
//// BOOST_REQUIRE(instance.create());
286286
////
287-
//// const auto record = table::prevout::record_put_ref{ {}, bogus_block };
287+
//// const auto record = table::prevout::put_ref{ {}, bogus_block };
288288
//// BOOST_REQUIRE(instance.put(2, record));
289289
////
290290
//// table::prevout::record_get element{};
@@ -367,7 +367,7 @@
367367
//// table::prevout instance{ head_store, body_store, 5 };
368368
//// BOOST_REQUIRE(instance.create());
369369
////
370-
//// const auto record = table::prevout::record_put_ref{ {}, bogus_block };
370+
//// const auto record = table::prevout::put_ref{ {}, bogus_block };
371371
//// BOOST_REQUIRE(instance.put(2, record));
372372
////
373373
//// table::prevout::record_get element{};

0 commit comments

Comments
 (0)