Skip to content

Commit

Permalink
MemoryMappedRegion: use span
Browse files Browse the repository at this point in the history
  • Loading branch information
battlmonstr committed Mar 14, 2024
1 parent 76804fe commit 39ad8e4
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 114 deletions.
37 changes: 19 additions & 18 deletions cmd/capi/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ std::vector<SilkwormChainSnapshot> collect_all_snapshots(const SnapshotRepositor
SilkwormHeadersSnapshot raw_headers_snapshot{
.segment{
.file_path = make_path(segment_file),
.memory_address = header_snapshot->memory_file_address(),
.memory_length = header_snapshot->memory_file_size()},
.memory_address = header_snapshot->memory_file_region().data(),
.memory_length = header_snapshot->memory_file_region().size()},
.header_hash_index{
.file_path = make_path(segment_file.index_file()),
.memory_address = idx_header_hash->memory_file_address(),
.memory_length = idx_header_hash->memory_file_size()}};
.memory_address = idx_header_hash->memory_file_region().data(),
.memory_length = idx_header_hash->memory_file_region().size()}};
headers_snapshot_sequence.push_back(raw_headers_snapshot);
} break;
case SnapshotType::bodies: {
Expand All @@ -172,12 +172,12 @@ std::vector<SilkwormChainSnapshot> collect_all_snapshots(const SnapshotRepositor
SilkwormBodiesSnapshot raw_bodies_snapshot{
.segment{
.file_path = make_path(segment_file),
.memory_address = body_snapshot->memory_file_address(),
.memory_length = body_snapshot->memory_file_size()},
.memory_address = body_snapshot->memory_file_region().data(),
.memory_length = body_snapshot->memory_file_region().size()},
.block_num_index{
.file_path = make_path(segment_file.index_file()),
.memory_address = idx_body_number->memory_file_address(),
.memory_length = idx_body_number->memory_file_size()}};
.memory_address = idx_body_number->memory_file_region().data(),
.memory_length = idx_body_number->memory_file_region().size()}};
bodies_snapshot_sequence.push_back(raw_bodies_snapshot);
} break;
case SnapshotType::transactions: {
Expand All @@ -187,16 +187,16 @@ std::vector<SilkwormChainSnapshot> collect_all_snapshots(const SnapshotRepositor
SilkwormTransactionsSnapshot raw_transactions_snapshot{
.segment{
.file_path = make_path(segment_file),
.memory_address = tx_snapshot->memory_file_address(),
.memory_length = tx_snapshot->memory_file_size()},
.memory_address = tx_snapshot->memory_file_region().data(),
.memory_length = tx_snapshot->memory_file_region().size()},
.tx_hash_index{
.file_path = make_path(segment_file.index_file()),
.memory_address = idx_txn_hash->memory_file_address(),
.memory_length = idx_txn_hash->memory_file_size()},
.memory_address = idx_txn_hash->memory_file_region().data(),
.memory_length = idx_txn_hash->memory_file_region().size()},
.tx_hash_2_block_index{
.file_path = make_path(segment_file.index_file_for_type(SnapshotType::transactions_to_block)),
.memory_address = idx_txn_hash_2_block->memory_file_address(),
.memory_length = idx_txn_hash_2_block->memory_file_size()}};
.memory_address = idx_txn_hash_2_block->memory_file_region().data(),
.memory_length = idx_txn_hash_2_block->memory_file_region().size()}};
transactions_snapshot_sequence.push_back(raw_transactions_snapshot);
} break;
default:
Expand Down Expand Up @@ -351,10 +351,11 @@ int build_indexes(SilkwormHandle handle, const BuildIndexesSettings& settings, c
throw std::runtime_error("Snapshot not found in the repository:" + snapshot_name);
}

auto mmf = new SilkwormMemoryMappedFile();
mmf->file_path = make_path(snapshot->path());
mmf->memory_address = snapshot->memory_file_address();
mmf->memory_length = snapshot->memory_file_size();
auto mmf = new SilkwormMemoryMappedFile{
.file_path = make_path(snapshot->path()),
.memory_address = snapshot->memory_file_region().data(),
.memory_length = snapshot->memory_file_region().size(),
};
snapshots.push_back(mmf);
}

Expand Down
28 changes: 14 additions & 14 deletions silkworm/capi/silkworm_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,42 +426,42 @@ TEST_CASE_METHOD(CApiTest, "CAPI silkworm_add_snapshot", "[silkworm][capi]") {
SilkwormHeadersSnapshot valid_shs{
.segment = SilkwormMemoryMappedFile{
.file_path = header_snapshot_path_string.c_str(),
.memory_address = header_snapshot.memory_file_address(),
.memory_length = header_snapshot.memory_file_size(),
.memory_address = header_snapshot.memory_file_region().data(),
.memory_length = header_snapshot.memory_file_region().size(),
},
.header_hash_index = SilkwormMemoryMappedFile{
.file_path = header_index_path_string.c_str(),
.memory_address = header_snapshot.idx_header_hash()->memory_file_address(),
.memory_length = header_snapshot.idx_header_hash()->memory_file_size(),
.memory_address = header_snapshot.idx_header_hash()->memory_file_region().data(),
.memory_length = header_snapshot.idx_header_hash()->memory_file_region().size(),
},
};
SilkwormBodiesSnapshot valid_sbs{
.segment = SilkwormMemoryMappedFile{
.file_path = body_snapshot_path_string.c_str(),
.memory_address = body_snapshot.memory_file_address(),
.memory_length = body_snapshot.memory_file_size(),
.memory_address = body_snapshot.memory_file_region().data(),
.memory_length = body_snapshot.memory_file_region().size(),
},
.block_num_index = SilkwormMemoryMappedFile{
.file_path = body_index_path_string.c_str(),
.memory_address = body_snapshot.idx_body_number()->memory_file_address(),
.memory_length = body_snapshot.idx_body_number()->memory_file_size(),
.memory_address = body_snapshot.idx_body_number()->memory_file_region().data(),
.memory_length = body_snapshot.idx_body_number()->memory_file_region().size(),
},
};
SilkwormTransactionsSnapshot valid_sts{
.segment = SilkwormMemoryMappedFile{
.file_path = tx_snapshot_path_string.c_str(),
.memory_address = tx_snapshot.memory_file_address(),
.memory_length = tx_snapshot.memory_file_size(),
.memory_address = tx_snapshot.memory_file_region().data(),
.memory_length = tx_snapshot.memory_file_region().size(),
},
.tx_hash_index = SilkwormMemoryMappedFile{
.file_path = tx_hash_index_path_string.c_str(),
.memory_address = tx_snapshot.idx_txn_hash()->memory_file_address(),
.memory_length = tx_snapshot.idx_txn_hash()->memory_file_size(),
.memory_address = tx_snapshot.idx_txn_hash()->memory_file_region().data(),
.memory_length = tx_snapshot.idx_txn_hash()->memory_file_region().size(),
},
.tx_hash_2_block_index = SilkwormMemoryMappedFile{
.file_path = tx_hash2block_index_path_string.c_str(),
.memory_address = tx_snapshot.idx_txn_hash_2_block()->memory_file_address(),
.memory_length = tx_snapshot.idx_txn_hash_2_block()->memory_file_size(),
.memory_address = tx_snapshot.idx_txn_hash_2_block()->memory_file_region().data(),
.memory_length = tx_snapshot.idx_txn_hash_2_block()->memory_file_region().size(),
},
};

Expand Down
21 changes: 10 additions & 11 deletions silkworm/db/snapshots/rec_split/rec_split.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class RecSplit {
SILK_TRACE << "RecSplit encoded file path: " << encoded_file_->path();
check_minimum_length(kFirstMetadataHeaderLength);

const auto address = encoded_file_->address();
const auto address = encoded_file_->region().data();

encoded_file_->advise_sequential();

Expand Down Expand Up @@ -333,7 +333,7 @@ class RecSplit {
offset += kEliasFano32CountLength;
const uint64_t u = endian::load_big_u64(address + offset);
offset += kEliasFano32ULength;
std::span<uint8_t> remaining_data{address + offset, encoded_file_->length() - offset};
auto remaining_data = encoded_file_->region().subspan(offset);
ef_offsets_ = std::make_unique<EliasFano>(count, u, remaining_data);
offset += ef_offsets_->data().size() * sizeof(uint64_t);

Expand All @@ -359,7 +359,7 @@ class RecSplit {
golomb_param_max_index_ = golomb_param_size - 1;
offset += kGolombParamSizeLength;

MemoryMappedInputStream mmis{address + offset, encoded_file_->length() - offset};
MemoryMappedInputStream mmis{encoded_file_->region().subspan(offset)};

// Read Golomb-Rice codes
mmis >> golomb_rice_codes_;
Expand All @@ -369,7 +369,7 @@ class RecSplit {
mmis >> double_ef_index_;
offset += 5 * sizeof(uint64_t) + double_ef_index_.data().size() * sizeof(uint64_t);

SILKWORM_ASSERT(offset == encoded_file_->length());
SILKWORM_ASSERT(offset == encoded_file_->size());

encoded_file_->advise_random();

Expand Down Expand Up @@ -600,10 +600,10 @@ class RecSplit {
const auto record = operator()(murmur_hash_3(key, length));
const auto position = 1 + 8 + bytes_per_record_ * (record + 1);

const auto address = encoded_file_->address();
ensure(position + sizeof(uint64_t) < encoded_file_->length(),
const auto region = encoded_file_->region();
ensure(position + sizeof(uint64_t) < region.size(),
[&]() { return "position: " + std::to_string(position) + " plus 8 exceeds file length"; });
return endian::load_big_u64(address + position) & record_mask_;
return endian::load_big_u64(region.data() + position) & record_mask_;
}

//! Return the offset of the i-th element in the index. Perfect hash table lookup is not performed,
Expand Down Expand Up @@ -631,8 +631,7 @@ class RecSplit {
return std::filesystem::last_write_time(index_path_);
}

[[nodiscard]] uint8_t* memory_file_address() const { return encoded_file_ ? encoded_file_->address() : nullptr; }
[[nodiscard]] std::size_t memory_file_size() const { return encoded_file_ ? encoded_file_->length() : 0; }
[[nodiscard]] MemoryMappedRegion memory_file_region() const { return encoded_file_ ? encoded_file_->region() : MemoryMappedRegion{}; }

private:
static inline std::size_t skip_bits(std::size_t m) { return memo[m] & 0xFFFF; }
Expand Down Expand Up @@ -832,9 +831,9 @@ class RecSplit {
[[nodiscard]] inline uint64_t hash128_to_bucket(const hash128_t& hash) const { return remap128(hash.first, bucket_count_); }

void check_minimum_length(std::size_t minimum_length) {
if (encoded_file_ && encoded_file_->length() < minimum_length) {
if (encoded_file_ && encoded_file_->size() < minimum_length) {
throw std::runtime_error("index " + encoded_file_->path().filename().string() + " is too short: " +
std::to_string(encoded_file_->length()));
std::to_string(encoded_file_->size()));
}
}

Expand Down
13 changes: 7 additions & 6 deletions silkworm/db/snapshots/seg/decompressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,12 @@ Decompressor::~Decompressor() {

void Decompressor::open() {
compressed_file_ = std::make_unique<MemoryMappedFile>(compressed_path_, compressed_region_);
if (compressed_file_->length() < kMinimumFileSize) {
throw std::runtime_error("compressed file is too short: " + std::to_string(compressed_file_->length()));
auto compressed_file_size = compressed_file_->size();
if (compressed_file_size < kMinimumFileSize) {
throw std::runtime_error("compressed file is too short: " + std::to_string(compressed_file_size));
}

const auto address = compressed_file_->address();
const auto address = compressed_file_->region().data();

compressed_file_->advise_sequential();

Expand All @@ -338,10 +339,10 @@ void Decompressor::open() {

// Store the start offset and length of the data words
words_start_ = address + positions_dict_offset + position_dict_length;
words_length_ = compressed_file_->length() - (positions_dict_offset + position_dict_length);
SILKWORM_ASSERT(address + compressed_file_->length() == words_start_ + words_length_);
words_length_ = compressed_file_size - (positions_dict_offset + position_dict_length);
SILKWORM_ASSERT(address + compressed_file_size == words_start_ + words_length_);
SILK_TRACE << "Decompressor words start offset: " << (words_start_ - address) << " words length: " << words_length_
<< " total length: " << compressed_file_->length();
<< " total size: " << compressed_file_size;

compressed_file_->advise_random();
}
Expand Down
12 changes: 3 additions & 9 deletions silkworm/db/snapshots/snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,10 @@ Snapshot::Snapshot(SnapshotPath path)
Snapshot::Snapshot(SnapshotPath path, MemoryMappedRegion segment_region)
: path_(std::move(path)), decoder_{path_.path(), segment_region} {}

uint8_t* Snapshot::memory_file_address() const {
MemoryMappedRegion Snapshot::memory_file_region() const {
const auto memory_file{decoder_.memory_file()};
if (!memory_file) return nullptr;
return memory_file->address();
}

std::size_t Snapshot::memory_file_size() const {
const auto memory_file{decoder_.memory_file()};
if (!memory_file) return 0;
return memory_file->length();
if (!memory_file) return MemoryMappedRegion{};
return memory_file->region();
}

void Snapshot::reopen_segment() {
Expand Down
3 changes: 1 addition & 2 deletions silkworm/db/snapshots/snapshot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ class Snapshot {
[[nodiscard]] bool empty() const { return item_count() == 0; }
[[nodiscard]] std::size_t item_count() const { return decoder_.words_count(); }

[[nodiscard]] uint8_t* memory_file_address() const;
[[nodiscard]] std::size_t memory_file_size() const;
[[nodiscard]] MemoryMappedRegion memory_file_region() const;

void reopen_segment();
virtual void reopen_index() = 0;
Expand Down
2 changes: 1 addition & 1 deletion silkworm/db/snapshots/snapshot_decompressor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ TEST_CASE("Decompressor::Decompressor from memory", "[silkworm][node][seg][decom
SetLogVerbosityGuard guard{log::Level::kNone};
test::TemporarySnapshotFile tmp_snapshot{create_nonempty_snapshot_file()};
MemoryMappedFile mmf{tmp_snapshot.path()};
Decompressor decoder_from_memory{tmp_snapshot.path(), MemoryMappedRegion{mmf.address(), mmf.length()}};
Decompressor decoder_from_memory{tmp_snapshot.path(), mmf.region()};
CHECK(!decoder_from_memory.is_open());
CHECK(decoder_from_memory.compressed_path() == tmp_snapshot.path());
CHECK(decoder_from_memory.words_count() == 0);
Expand Down
32 changes: 16 additions & 16 deletions silkworm/infra/common/memory_mapped_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ MemoryMappedFile::MemoryMappedFile(std::filesystem::path path, std::optional<Mem
ensure(std::filesystem::is_regular_file(path_), [&]() { return "MemoryMappedFile: " + path_.string() + " is not regular file"; });

if (region) {
ensure(region->address != nullptr, "MemoryMappedFile: address is null");
ensure(region->length > 0, "MemoryMappedFile: length is zero");
address_ = region->address;
length_ = region->length;
ensure(region->data() != nullptr, "MemoryMappedFile: address is null");
ensure(!region->empty(), "MemoryMappedFile: length is zero");
region_ = *region;
} else {
map_existing(read_only);
}
Expand Down Expand Up @@ -84,9 +83,10 @@ void MemoryMappedFile::map_existing(bool read_only) {

[[maybe_unused]] auto _ = gsl::finally([fd]() { if (INVALID_HANDLE_VALUE != fd) ::CloseHandle(fd); });

length_ = std::filesystem::file_size(path_);
auto size = std::filesystem::file_size(path_);
auto address = static_cast<uint8_t*>(mmap(fd, size, read_only));
region_ = {address, size};

address_ = static_cast<uint8_t*>(mmap(fd, read_only));
fd = INVALID_HANDLE_VALUE;
}

Expand All @@ -99,7 +99,7 @@ void MemoryMappedFile::advise_random() {
void MemoryMappedFile::advise_sequential() {
}

void* MemoryMappedFile::mmap(FileDescriptor fd, bool read_only) {
void* MemoryMappedFile::mmap(FileDescriptor fd, size_t size, bool read_only) {
DWORD protection = static_cast<DWORD>(read_only ? PAGE_READONLY : PAGE_READWRITE);

mapping_ = ::CreateFileMapping(fd, nullptr, protection, 0, 0, nullptr); // note: no size specified to avoid MapViewOfFile failure
Expand All @@ -108,7 +108,7 @@ void* MemoryMappedFile::mmap(FileDescriptor fd, bool read_only) {
}

DWORD desired_access = static_cast<DWORD>(read_only ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
void* memory = (LPTSTR)::MapViewOfFile(mapping_, desired_access, 0, static_cast<DWORD>(0), length_);
void* memory = (LPTSTR)::MapViewOfFile(mapping_, desired_access, 0, static_cast<DWORD>(0), size);

if (memory == nullptr) {
throw std::runtime_error{"MapViewOfFile failed for: " + path_.string() + " error: " + std::to_string(GetLastError())};
Expand Down Expand Up @@ -142,9 +142,9 @@ void MemoryMappedFile::map_existing(bool read_only) {
}
[[maybe_unused]] auto _ = gsl::finally([fd]() { ::close(fd); });

length_ = std::filesystem::file_size(path_);

address_ = static_cast<uint8_t*>(mmap(fd, read_only));
auto size = std::filesystem::file_size(path_);
auto address = static_cast<uint8_t*>(mmap(fd, size, read_only));
region_ = {address, size};
}

void MemoryMappedFile::advise_normal() {
Expand All @@ -159,10 +159,10 @@ void MemoryMappedFile::advise_sequential() {
advise(MADV_SEQUENTIAL);
}

void* MemoryMappedFile::mmap(FileDescriptor fd, bool read_only) {
void* MemoryMappedFile::mmap(FileDescriptor fd, size_t size, bool read_only) {
int flags = MAP_SHARED;

const auto address = ::mmap(nullptr, length_, read_only ? PROT_READ : (PROT_READ | PROT_WRITE), flags, fd, 0);
const auto address = ::mmap(nullptr, size, read_only ? PROT_READ : (PROT_READ | PROT_WRITE), flags, fd, 0);
if (address == MAP_FAILED) {
throw std::runtime_error{"mmap failed for: " + path_.string() + " error: " + safe_strerror(errno)};
}
Expand All @@ -171,16 +171,16 @@ void* MemoryMappedFile::mmap(FileDescriptor fd, bool read_only) {
}

void MemoryMappedFile::unmap() {
if (address_ != nullptr) {
const int result = ::munmap(address_, length_);
if (region_.data() != nullptr) {
const int result = ::munmap(region_.data(), region_.size());
if (result == -1) {
throw std::runtime_error{"munmap failed for: " + path_.string() + " error: " + safe_strerror(errno)};
}
}
}

void MemoryMappedFile::advise(int advice) {
const int result = ::madvise(address_, length_, advice);
const int result = ::madvise(region_.data(), region_.size(), advice);
if (result == -1) {
// Ignore not implemented in kernel error because it still works (from Erigon)
if (errno != ENOSYS) {
Expand Down
Loading

0 comments on commit 39ad8e4

Please sign in to comment.