Skip to content

Commit 5e9d38e

Browse files
authored
Merge pull request #581 from evoskuil/master
Add overrides to hashmap, write key in unlinked tx.set, contiguous txs.
2 parents 4e422e1 + 2e00bef commit 5e9d38e

13 files changed

Lines changed: 207 additions & 84 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_read.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ size_t CLASS::get_tx_count(const header_link& link) const NOEXCEPT
9696
if (!store_.txs.find(link, txs))
9797
return {};
9898

99-
return txs.quantity;
99+
return txs.number;
100100
}
101101

102102
TEMPLATE

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

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,18 @@ bool CLASS::set(const block& block, bool strong) NOEXCEPT
7777
TEMPLATE
7878
code CLASS::set_code(const transaction& tx) NOEXCEPT
7979
{
80-
tx_link unused{};
81-
return set_code(unused, tx);
80+
constexpr auto txs = system::possible_narrow_cast<tx_link::integer>(one);
81+
82+
// Allocate tx record.
83+
const auto tx_fk = store_.tx.allocate(txs);
84+
if (tx_fk.is_terminal())
85+
return error::tx_tx_allocate;
86+
87+
return set_code(tx_fk, tx);
8288
}
8389

8490
TEMPLATE
85-
code CLASS::set_code(tx_link& tx_fk, const transaction& tx) NOEXCEPT
91+
code CLASS::set_code(const tx_link& tx_fk, const transaction& tx) NOEXCEPT
8692
{
8793
// This is the only multitable write query (except initialize/genesis).
8894
using namespace system;
@@ -92,19 +98,13 @@ code CLASS::set_code(tx_link& tx_fk, const transaction& tx) NOEXCEPT
9298
using ix = linkage<schema::index>;
9399
const auto& ins = tx.inputs_ptr();
94100
const auto& ous = tx.outputs_ptr();
95-
const auto txs = possible_narrow_cast<tx_link::integer>(one);
96101
const auto inputs = possible_narrow_cast<ix::integer>(ins->size());
97102
const auto outputs = possible_narrow_cast<ix::integer>(ous->size());
98103

99104

100105
// ========================================================================
101106
const auto scope = store_.get_transactor();
102107

103-
// Allocate tx record.
104-
tx_fk = store_.tx.allocate(txs);
105-
if (tx_fk.is_terminal())
106-
return error::tx_tx_allocate;
107-
108108
// Allocate contiguously and store inputs.
109109
input_link in_fk{};
110110
if (!store_.input.put_link(in_fk, table::input::put_ref{ {}, tx }))
@@ -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,
@@ -321,46 +321,48 @@ TEMPLATE
321321
code CLASS::set_code(txs_link& out_fk, const block& block,
322322
const header_link& key, bool strong) NOEXCEPT
323323
{
324+
using namespace system;
324325
if (key.is_terminal())
325326
return error::txs_header;
326327

327-
const auto count = block.transactions();
328-
if (is_zero(count))
328+
const auto txs = block.transactions();
329+
if (is_zero(txs))
329330
return error::txs_empty;
330331

332+
const auto count = possible_narrow_cast<tx_link::integer>(txs);
333+
const auto tx_fks = store_.tx.allocate(count);
334+
if (tx_fks.is_terminal())
335+
return error::tx_tx_allocate;
336+
331337
code ec{};
332-
tx_link tx_fk{};
333-
tx_links links{};
334-
links.reserve(count);
338+
auto fk = tx_fks;
339+
340+
// Each tx is set under a distinct transactor.
335341
for (const auto& tx: *block.transactions_ptr())
336-
{
337-
// Each tx is set under a distinct transactor.
338-
if ((ec = set_code(tx_fk, *tx)))
342+
if ((ec = set_code(fk++, *tx)))
339343
return ec;
340344

341-
links.push_back(tx_fk.value);
342-
}
343-
344345
using bytes = linkage<schema::size>::integer;
345346
const auto size = block.serialized_size(true);
346-
const auto wire = system::possible_narrow_cast<bytes>(size);
347+
const auto wire = possible_narrow_cast<bytes>(size);
347348

348349
// ========================================================================
349350
const auto scope = store_.get_transactor();
350351
constexpr auto positive = true;
351352

352353
// Clean allocation failure (e.g. disk full), see set_strong() comments.
353354
// Transactor assures cannot be restored without txs, as required to unset.
354-
if (strong && !set_strong(key, links, positive))
355+
if (strong && !set_strong(key, txs, tx_fks, positive))
355356
return error::txs_confirm;
356357

357358
// Header link is the key for the txs table.
358359
// Clean single allocation failure (e.g. disk full).
359-
out_fk = store_.txs.put_link(key, table::txs::slab
360+
out_fk = store_.txs.put_link(key, table::txs::put_group
360361
{
361362
{},
362363
wire,
363-
links
364+
count,
365+
tx_fks
364366
});
365367

366368
return out_fk.is_terminal() ? error::txs_txs_put : error::success;

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,6 @@ code CLASS::block_confirmable(const header_link& link) const NOEXCEPT
411411
// ----------------------------------------------------------------------------
412412

413413
// protected
414-
// This is also invoked from block.txs archival (when checkpoint/milestone).
415414
TEMPLATE
416415
bool CLASS::set_strong(const header_link& link, const tx_links& txs,
417416
bool positive) NOEXCEPT
@@ -436,6 +435,34 @@ bool CLASS::set_strong(const header_link& link, const tx_links& txs,
436435
return true;
437436
}
438437

438+
// protected
439+
// This is invoked from block.txs archival (when checkpoint/milestone).
440+
TEMPLATE
441+
bool CLASS::set_strong(const header_link& link, size_t count,
442+
const tx_link& first_fk, bool positive) NOEXCEPT
443+
{
444+
using namespace system;
445+
using link_t = table::strong_tx::link;
446+
using element_t = table::strong_tx::record;
447+
448+
// Preallocate all strong_tx records for the block and reuse memory ptr.
449+
const auto records = possible_narrow_cast<link_t::integer>(count);
450+
auto record = store_.strong_tx.allocate(records);
451+
const auto ptr = store_.strong_tx.get_memory();
452+
const auto end = first_fk + count;
453+
454+
// Contiguous tx links.
455+
for (auto fk = first_fk; fk < end; ++fk)
456+
if (!store_.strong_tx.put(ptr, record++, fk, element_t
457+
{
458+
{},
459+
link,
460+
positive
461+
})) return false;
462+
463+
return true;
464+
}
465+
439466
TEMPLATE
440467
bool CLASS::set_strong(const header_link& link) NOEXCEPT
441468
{

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/query.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,6 @@ class query
374374

375375
/// Set transaction.
376376
code set_code(const transaction& tx) NOEXCEPT;
377-
code set_code(tx_link& tx_fk, const transaction& tx) NOEXCEPT;
378377

379378
/// Set header (headers-first).
380379
code set_code(const header& header, const context& ctx,
@@ -563,6 +562,8 @@ class query
563562
const tx_link& prevout_tx, uint32_t version,
564563
const context& ctx) const NOEXCEPT;
565564

565+
bool set_strong(const header_link& link, size_t count,
566+
const tx_link& first_fk, bool positive) NOEXCEPT;
566567
bool set_strong(const header_link& link, const tx_links& txs,
567568
bool positive) NOEXCEPT;
568569

@@ -601,6 +602,10 @@ class query
601602
const system::settings& settings, const header& header,
602603
const header_link& link, size_t height) const NOEXCEPT;
603604

605+
/// tx_fk must be allocated.
606+
/// -----------------------------------------------------------------------
607+
code set_code(const tx_link& tx_fk, const transaction& tx) NOEXCEPT;
608+
604609
private:
605610
struct maybe_strong
606611
{

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.

0 commit comments

Comments
 (0)