Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/bitcoin/database/impl/primitives/body.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ inline memory CLASS::get(const Link& link) const NOEXCEPT

TEMPLATE
template <size_t Column>
inline memory::iterator CLASS::get_raw1(const Link& link) const NOEXCEPT
inline memory::iterator CLASS::get_raw(const Link& link) const NOEXCEPT
{
if (link.is_terminal())
return {};
Expand Down Expand Up @@ -198,7 +198,7 @@ constexpr size_t CLASS::stride() NOEXCEPT
// Slab: link/key incorporated into size (byte-addressed map).
return size;
}
else if constexpr (is_zero(Column) && is_nonzero(key_size))
else if constexpr (is_zero(Column) && keys::keyed<Key>())
{
// Spine of a keyed map: link/key precede the record.
return Link::size + key_size + size;
Expand Down
14 changes: 6 additions & 8 deletions include/bitcoin/database/impl/primitives/hashmap.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ bool CLASS::verify() const NOEXCEPT
TEMPLATE
bool CLASS::enabled() const NOEXCEPT
{
return head_.buckets() > one;
return !is_zero(head_.buckets());
}

TEMPLATE
Expand Down Expand Up @@ -297,7 +297,7 @@ bool CLASS::set(const memory& ptr, const Link& link, const Key& key,
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand All @@ -307,12 +307,10 @@ bool CLASS::set(const memory& ptr, const Link& link, const Key& key,
return false;

// Set element search key.
unsafe_array_cast<uint8_t, key_size>(std::next(offset,
Link::size)) = key;

iostream stream{ offset, size - position };
finalizer sink{ stream };
sink.skip_bytes(index_size);
sink.skip_bytes(Link::size);
keys::write(sink, key);

// Due to accounting, record hashmaps are limited to set(1).
if constexpr (!is_slab) { BC_ASSERT(is_one(element.count())); }
Expand Down Expand Up @@ -499,7 +497,7 @@ bool CLASS::read(const memory& ptr, const Link& link, Element& element) NOEXCEPT
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down Expand Up @@ -539,7 +537,7 @@ bool CLASS::write(Link& previous, const memory& ptr, const Link& link,
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down
40 changes: 33 additions & 7 deletions include/bitcoin/database/impl/primitives/hashmaps.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ bool CLASS::verify() const NOEXCEPT
TEMPLATE
bool CLASS::enabled() const NOEXCEPT
{
return head_.buckets() > one;
return !is_zero(head_.buckets());
}

TEMPLATE
Expand Down Expand Up @@ -293,7 +293,7 @@ bool CLASS::set(const memory& ptr, const Link& link, const Key& key,
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down Expand Up @@ -469,7 +469,7 @@ bool CLASS::get(const memory& ptr, const Link& link, Element& element) NOEXCEPT
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand All @@ -491,18 +491,44 @@ bool CLASS::get(const Link& link, Element& element) const NOEXCEPT
return get<Column>(get_memory<Column>(), link, element);
}

TEMPLATE
template <size_t Column, typename Element>
bool CLASS::get_raw(const Link& link, Element& element) const NOEXCEPT
{
return get<Column>(body_.template get_raw<Column>(link), element);
}

TEMPLATE
template <size_t Column, typename Element>
bool CLASS::put(const Link& link, const Element& element) NOEXCEPT
{
const auto ptr = body_.template get_raw1<Column>(link);
const auto ptr = body_.template get_raw<Column>(link);
if (!put<Column>(ptr, element))
return false;

body_.complete(link, element.count());
return true;
}

// protected (unguarded memory access)
TEMPLATE
template <size_t Column, typename Element>
bool CLASS::get(memory::iterator it, Element& element) const NOEXCEPT
{
static_assert(is_nonzero(Column), "column zero is the keyed spine");
static_assert(Element::size == width<Column>);
if (is_null(it))
return false;

using namespace system;
const auto bytes = width<Column> * element.count();
iostream stream{ it, possible_narrow_sign_cast<ptrdiff_t>(bytes) };
reader source{ stream };

BC_DEBUG_ONLY(source.set_limit(width<Column> * element.count());)
return element.from_data(source);
}

// protected (unguarded memory access)
TEMPLATE
template <size_t Column, typename Element>
Expand All @@ -515,7 +541,7 @@ bool CLASS::put(memory::iterator it, const Element& element) NOEXCEPT

using namespace system;
const auto bytes = width<Column> * element.count();
iostream stream{ it, possible_narrow_and_sign_cast<ptrdiff_t>(bytes) };
iostream stream{ it, possible_narrow_sign_cast<ptrdiff_t>(bytes) };
flipper sink{ stream };

BC_DEBUG_ONLY(sink.set_limit(width<Column> * element.count());)
Expand Down Expand Up @@ -567,7 +593,7 @@ bool CLASS::read(const memory& ptr, const Link& link, Element& element) NOEXCEPT
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down Expand Up @@ -607,7 +633,7 @@ bool CLASS::write(Link& previous, const memory& ptr, const Link& link,
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down
40 changes: 35 additions & 5 deletions include/bitcoin/database/impl/primitives/keys.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ template <class Key>
INLINE constexpr size_t size() NOEXCEPT
{
using namespace system;
if constexpr (is_same_type<Key, chain::point>)
if constexpr (is_search<Key>)
{
return Key::width;
}
else if constexpr (is_same_type<Key, chain::point>)
{
// Index is truncated to three bytes.
return sub1(chain::point::serialized_size());
Expand All @@ -55,6 +59,13 @@ INLINE constexpr size_t size() NOEXCEPT
}
}

template <class Key>
INLINE constexpr bool keyed() NOEXCEPT
{
using namespace system;
return !is_same_type<Key, data_array<zero>>;
}

template <class Key, class Integral>
INLINE Integral bucket(const Key& key, Integral buckets) NOEXCEPT
{
Expand All @@ -80,7 +91,11 @@ template <class Key>
INLINE uint64_t hash(const Key& key) NOEXCEPT
{
using namespace system;
if constexpr (is_same_type<Key, chain::point>)
if constexpr (is_search<Key>)
{
return hash(key.value);
}
else if constexpr (is_same_type<Key, chain::point>)
{
// Both produce an 85% Poisson distribution.
return fnv1a_combine(hash(key.hash()), key.index());
Expand All @@ -103,7 +118,11 @@ template <class Key>
INLINE uint64_t thumb(const Key& key) NOEXCEPT
{
using namespace system;
if constexpr (is_same_type<Key, system::chain::point>)
if constexpr (is_search<Key>)
{
return thumb(key.value);
}
else if constexpr (is_same_type<Key, system::chain::point>)
{
// spread point.index across point.hash extraction, as otherwise the
// unlikely bucket collisions of points of the same hash will not be
Expand Down Expand Up @@ -133,7 +152,13 @@ template <class Key>
INLINE void write(writer& sink, const Key& key) NOEXCEPT
{
using namespace system;
if constexpr (is_same_type<Key, chain::point>)
if constexpr (is_search<Key>)
{
if constexpr (is_nonzero(Key::width))
sink.write_bytes(std::next(key.value.data(), Key::offset),
Key::width);
}
else if constexpr (is_same_type<Key, chain::point>)
{
sink.write_bytes(key.hash());
sink.write_3_bytes_little_endian(key.index());
Expand All @@ -149,7 +174,12 @@ INLINE bool compare(const Array& bytes, const Key& key) NOEXCEPT
{
using namespace system;
static_assert(size<Key>() <= array_count<Array>);
if constexpr (is_same_type<Key, chain::point>)
if constexpr (is_search<Key>)
{
return std::equal(bytes.cbegin(), bytes.cend(),
std::next(key.value.cbegin(), Key::offset));
}
else if constexpr (is_same_type<Key, chain::point>)
{
// Index is truncated to three bytes.
const auto index = key.index();
Expand Down
27 changes: 25 additions & 2 deletions include/bitcoin/database/impl/primitives/nomap.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ bool CLASS::get(const memory& ptr, const Link& link, Element& element) NOEXCEPT
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand All @@ -197,6 +197,29 @@ bool CLASS::get(const memory& ptr, const Link& link, Element& element) NOEXCEPT
return element.from_data(source);
}

// static
TEMPLATE
template <typename Element>
bool CLASS::raw(const memory& ptr, const Link& link, Element& element) NOEXCEPT
{
using namespace system;
if (!ptr || link.is_terminal())
return false;

const auto start = body::link_to_position(link);
if (is_limited<ptrdiff_t>(start))
return false;

if (possible_narrow_sign_cast<ptrdiff_t>(start) >= ptr.size())
return false;

const auto offset = ptr.offset(start);
if (is_null(offset))
return false;

return element.from_data(offset);
}

TEMPLATE
template <typename Element, if_equal<Element::size, Size>>
inline bool CLASS::get(const Link& link, Element& element) const NOEXCEPT
Expand Down Expand Up @@ -258,7 +281,7 @@ bool CLASS::put(const memory& ptr, const Link& link,
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down
6 changes: 3 additions & 3 deletions include/bitcoin/database/impl/primitives/nomaps.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ bool CLASS::get(const memory& ptr, const Link& link, Element& element) NOEXCEPT
return false;

const auto size = ptr.size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
const auto position = possible_narrow_sign_cast<ptrdiff_t>(start);
if (position >= size)
return false;

Expand Down Expand Up @@ -185,7 +185,7 @@ TEMPLATE
template <size_t Column, typename Element>
bool CLASS::put(const Link& link, const Element& element) NOEXCEPT
{
const auto ptr = body_.template get_raw1<Column>(link);
const auto ptr = body_.template get_raw<Column>(link);
if (!put<Column>(ptr, element))
return false;

Expand All @@ -204,7 +204,7 @@ bool CLASS::put(memory::iterator it, const Element& element) NOEXCEPT

using namespace system;
const auto bytes = width<Column> * element.count();
iostream stream{ it, possible_narrow_and_sign_cast<ptrdiff_t>(bytes) };
iostream stream{ it, possible_narrow_sign_cast<ptrdiff_t>(bytes) };
flipper sink{ stream };

BC_DEBUG_ONLY(sink.set_limit(width<Column> * element.count());)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ code CLASS::get_address_txs(const stopper& cancel, tx_links& out,
const hash_digest& key, size_t limit) const NOEXCEPT
{
output_links links{};
address_link cursor{};
outs_link cursor{};
if (const auto ec = to_address_outputs(cancel, cursor, links, key, limit))
return ec;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ typename CLASS::transaction::cptr CLASS::get_transaction(const tx_link& link,

table::outs::record outs{};
outs.out_fks.resize(tx.outs_count);
if (!store_.outs.get(tx.outs_fk, outs))
if (!store_.outs.puts.get(tx.outs_fk, outs))
return {};

const auto inputs = to_shared<chain::input_cptrs>();
Expand Down
35 changes: 15 additions & 20 deletions include/bitcoin/database/impl/query/archive/chain_writer.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,20 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction& tx,

insert.reset();

// Allocate and contiguously store output links.
outs_link outs_fk{};
if (!store_.outs.put_link(outs_fk,
// Allocate outs/address rows and contiguously store output links.
// Address spine elements are committed into the same rows, below.
auto outs_fk = store_.outs.allocate(outputs);
if (outs_fk.is_terminal())
return error::tx_outs_put;

// Outs put is unguarded, the accessor guards its rows against remap.
auto outsert = store_.outs.get_memory();
if (!outsert || !store_.outs.puts.put(outs_fk,
table::outs::put_ref{ {}, out_fk, tx }))
return error::tx_outs_put;

outsert.reset();

// Create tx record.
// Commit is deferred for point/address index consistency.
if (!store_.tx.set(tx_fk, tx.get_hash(false), table::transaction::put_ref
Expand Down Expand Up @@ -207,27 +215,14 @@ code CLASS::set_code(const tx_link& tx_fk, const transaction& tx,
}
}

// Commit address index records (hashmap).
// Commit address index records (hashmap, rows shared with outs).
if (address_enabled())
{
auto ad_fk = store_.address.allocate(outputs);
if (ad_fk.is_terminal())
return error::tx_address_allocate;

constexpr auto value_parent = sizeof(uint64_t) - tx_link::size;
const auto ptr = store_.address.get_memory();
auto ad_fk = outs_fk;
const auto ptr = store_.outs.get_memory();
for (const auto& output: *ous)
{
if (!store_.address.put(ptr, ad_fk++, output->script().hash(),
table::address::record{ {}, out_fk }))
if (!store_.outs.commit(ptr, ad_fk++, { output->script().hash() }))
return error::tx_address_put;

// See outs::put_ref.
// Calculate next corresponding output fk from serialized size.
// (variable_size(value) + (value + script)) - (value - parent)
out_fk += variable_size(output->value()) +
output->serialized_size() - value_parent;
}
}

// Commit tx to search (hashmap).
Expand Down
Loading
Loading