Skip to content

Commit

Permalink
Update storage interface, impl, test to support dynamic head.
Browse files Browse the repository at this point in the history
  • Loading branch information
evoskuil committed Jan 7, 2025
1 parent f91d721 commit b2ea049
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 11 deletions.
4 changes: 4 additions & 0 deletions include/bitcoin/database/memory/interfaces/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class storage
/// Allocate bytes and return offset to first allocated (or eof).
virtual size_t allocate(size_t chunk) NOEXCEPT = 0;

/// Get remap-protected r/w access to offset (or null) allocated to size.
virtual memory_ptr set(size_t offset, size_t size,
uint8_t backfill) NOEXCEPT = 0;

/// Get remap-protected r/w access to start/offset of memory map (or null).
virtual memory_ptr get(size_t offset=zero) const NOEXCEPT = 0;

Expand Down
4 changes: 4 additions & 0 deletions include/bitcoin/database/memory/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ class BCD_API map
/// Allocate bytes and return offset to first allocated (or eof).
size_t allocate(size_t chunk) NOEXCEPT override;

/// Get remap-protected r/w access to offset (or null) allocated to size.
memory_ptr set(size_t offset, size_t size,
uint8_t backfill) NOEXCEPT override;

/// Get remap-protected r/w access to start/offset of memory map (or null).
memory_ptr get(size_t offset=zero) const NOEXCEPT override;

Expand Down
38 changes: 36 additions & 2 deletions src/memory/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,20 +242,54 @@ size_t map::allocate(size_t chunk) NOEXCEPT
auto end = logical_ + chunk;
if (end > capacity_)
{
const auto size = to_capacity(end);
const auto new_capacity = to_capacity(end);

// TODO: Could loop over a try lock here and log deadlock warning.
std::unique_lock remap_lock(remap_mutex_);

// Disk full condition leaves store in valid state despite eof return.
if (!remap_(size))
if (!remap_(new_capacity))
return storage::eof;
}

std::swap(logical_, end);
return end;
}

memory_ptr map::set(size_t offset, size_t size, uint8_t backfill) NOEXCEPT
{
{
std::unique_lock field_lock(field_mutex_);

if (fault_ || !loaded_ || is_add_overflow(offset, size))
return {};

const auto end = std::max(logical_, offset + size);
if (end > capacity_)
{
const auto old_capacity = capacity_;
const auto new_capacity = to_capacity(end);

// TODO: Could loop over a try lock here and log deadlock warning.
std::unique_lock remap_lock(remap_mutex_);

// Disk full condition leaves store in valid state despite null.
if (!remap_(new_capacity))
return {};

// Fill new capacity as offset may not be at end due to expansion.
BC_PUSH_WARNING(NO_POINTER_ARITHMETIC)
std::fill_n(memory_map_ + old_capacity, new_capacity - old_capacity,
backfill);
BC_POP_WARNING()
}

logical_ = end;
}

return get(offset);
}

memory_ptr map::get(size_t offset) const NOEXCEPT
{
// Obtaining logical before access prevents mutual mutex wait (deadlock).
Expand Down
Loading

0 comments on commit b2ea049

Please sign in to comment.