Skip to content

Commit 112ced3

Browse files
authored
db: BodySnapshotFreezer use sequential txn_id without gaps (#2215)
1 parent 2d57336 commit 112ced3

12 files changed

+82
-26
lines changed

silkworm/db/access_layer.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,16 +1320,21 @@ std::optional<BlockHeader> DataModel::read_header_from_snapshot(const Hash& hash
13201320
return block_header;
13211321
}
13221322

1323-
bool DataModel::read_body_from_snapshot(BlockNum height, BlockBody& body) {
1323+
std::optional<BlockBodyForStorage> DataModel::read_body_for_storage_from_snapshot(BlockNum height) {
13241324
if (!repository_) {
1325-
return false;
1325+
return std::nullopt;
13261326
}
13271327

13281328
// We know the body snapshot in advance: find it based on target block number
13291329
const auto snapshot_and_index = repository_->find_segment(SnapshotType::bodies, height);
1330-
if (!snapshot_and_index) return false;
1330+
if (!snapshot_and_index) return std::nullopt;
13311331

13321332
auto stored_body = BodyFindByBlockNumQuery{*snapshot_and_index}.exec(height);
1333+
return stored_body;
1334+
}
1335+
1336+
bool DataModel::read_body_from_snapshot(BlockNum height, BlockBody& body) {
1337+
auto stored_body = read_body_for_storage_from_snapshot(height);
13331338
if (!stored_body) return false;
13341339

13351340
// Skip first and last *system transactions* in block body

silkworm/db/access_layer.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,9 @@ class DataModel {
317317
[[nodiscard]] bool read_body(const Hash& hash, BlockNum height, BlockBody& body) const;
318318
[[nodiscard]] bool read_body(const Hash& hash, BlockBody& body) const;
319319

320+
//! Read block body for storage from the snapshot repository
321+
[[nodiscard]] static std::optional<BlockBodyForStorage> read_body_for_storage_from_snapshot(BlockNum height);
322+
320323
//! Read the canonical block header at specified height
321324
[[nodiscard]] std::optional<Hash> read_canonical_hash(BlockNum height) const;
322325

silkworm/db/bodies/body_snapshot_freezer.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,20 @@
2424

2525
namespace silkworm::db {
2626

27-
void BodySnapshotFreezer::copy(ROTxn& txn, BlockNumRange range, snapshots::SnapshotFileWriter& file_writer) const {
27+
void BodySnapshotFreezer::copy(ROTxn& txn, const FreezerCommand& command, snapshots::SnapshotFileWriter& file_writer) const {
28+
BlockNumRange range = command.range;
29+
uint64_t base_txn_id = command.base_txn_id;
30+
2831
snapshots::BodySnapshotWriter writer{file_writer};
2932
auto out = writer.out();
3033
for (BlockNum i = range.first; i < range.second; i++) {
3134
auto value_opt = read_canonical_body_for_storage(txn, i);
3235
if (!value_opt) throw std::runtime_error{"BodySnapshotFreezer::copy missing body for block " + std::to_string(i)};
33-
*out++ = *value_opt;
36+
BlockBodyForStorage& value = *value_opt;
37+
// remap to sequential values without gaps (see txnum.go)
38+
value.base_txn_id = base_txn_id;
39+
base_txn_id += value.txn_count;
40+
*out++ = value;
3441
}
3542
}
3643

silkworm/db/bodies/body_snapshot_freezer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace silkworm::db {
2323
class BodySnapshotFreezer : public SnapshotFreezer {
2424
public:
2525
~BodySnapshotFreezer() override = default;
26-
void copy(ROTxn& txn, BlockNumRange range, snapshots::SnapshotFileWriter& file_writer) const override;
26+
void copy(ROTxn& txn, const FreezerCommand& command, snapshots::SnapshotFileWriter& file_writer) const override;
2727
void cleanup(RWTxn& txn, BlockNumRange range) const override;
2828
};
2929

silkworm/db/data_migration.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@
1818

1919
#include <memory>
2020

21-
namespace silkworm::db {
21+
#include "data_migration_command.hpp"
2222

23-
struct DataMigrationCommand {
24-
virtual ~DataMigrationCommand() = default;
25-
};
23+
namespace silkworm::db {
2624

2725
struct DataMigrationResult {
2826
virtual ~DataMigrationResult() = default;
@@ -34,7 +32,7 @@ struct DataMigration {
3432
void run();
3533

3634
protected:
37-
virtual std::unique_ptr<DataMigrationCommand> next_command();
35+
virtual std::unique_ptr<DataMigrationCommand> next_command() = 0;
3836
virtual std::shared_ptr<DataMigrationResult> migrate(std::unique_ptr<DataMigrationCommand> command) = 0;
3937
virtual void index(std::shared_ptr<DataMigrationResult> result) = 0;
4038
virtual void commit(std::shared_ptr<DataMigrationResult> result) = 0;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
Copyright 2024 The Silkworm Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
namespace silkworm::db {
20+
21+
struct DataMigrationCommand {
22+
virtual ~DataMigrationCommand() = default;
23+
};
24+
25+
} // namespace silkworm::db

silkworm/db/freezer.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ namespace silkworm::db {
3737

3838
using namespace silkworm::snapshots;
3939

40-
struct FreezerCommand : public DataMigrationCommand {
41-
BlockNumRange range;
42-
43-
explicit FreezerCommand(BlockNumRange range1)
44-
: range(std::move(range1)) {}
45-
~FreezerCommand() override = default;
46-
};
47-
4840
struct FreezerResult : public DataMigrationResult {
4941
SnapshotBundle bundle;
5042

@@ -63,6 +55,12 @@ static BlockNum get_first_stored_header_num(ROTxn& txn) {
6355
return num_opt.value_or(0);
6456
}
6557

58+
static std::optional<uint64_t> get_next_base_txn_id(BlockNum number) {
59+
auto body = DataModel::read_body_for_storage_from_snapshot(number);
60+
if (!body) return std::nullopt;
61+
return body->base_txn_id + body->txn_count;
62+
}
63+
6664
std::unique_ptr<DataMigrationCommand> Freezer::next_command() {
6765
BlockNum last_frozen = snapshots_.max_block_available();
6866
BlockNum start = (last_frozen > 0) ? last_frozen + 1 : 0;
@@ -73,8 +71,15 @@ std::unique_ptr<DataMigrationCommand> Freezer::next_command() {
7371
return get_tip_num(db_tx);
7472
}();
7573

74+
uint64_t base_txn_id = [last_frozen]() -> uint64_t {
75+
if (last_frozen == 0) return 0;
76+
auto id = get_next_base_txn_id(last_frozen);
77+
assert(id.has_value());
78+
return *id;
79+
}();
80+
7681
if (end + kFullImmutabilityThreshold <= tip) {
77-
return std::make_unique<FreezerCommand>(FreezerCommand{{start, end}});
82+
return std::make_unique<FreezerCommand>(FreezerCommand{{start, end}, base_txn_id});
7883
}
7984
return {};
8085
}
@@ -108,7 +113,7 @@ std::shared_ptr<DataMigrationResult> Freezer::migrate(std::unique_ptr<DataMigrat
108113
{
109114
auto db_tx = db_access_.start_ro_tx();
110115
auto& freezer = get_snapshot_freezer(path.type());
111-
freezer.copy(db_tx, range, file_writer);
116+
freezer.copy(db_tx, freezer_command, file_writer);
112117
}
113118
SnapshotFileWriter::flush(std::move(file_writer));
114119
}

silkworm/db/headers/header_snapshot_freezer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424

2525
namespace silkworm::db {
2626

27-
void HeaderSnapshotFreezer::copy(ROTxn& txn, BlockNumRange range, snapshots::SnapshotFileWriter& file_writer) const {
27+
void HeaderSnapshotFreezer::copy(ROTxn& txn, const FreezerCommand& command, snapshots::SnapshotFileWriter& file_writer) const {
28+
BlockNumRange range = command.range;
2829
snapshots::HeaderSnapshotWriter writer{file_writer};
2930
auto out = writer.out();
3031
for (BlockNum i = range.first; i < range.second; i++) {

silkworm/db/headers/header_snapshot_freezer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace silkworm::db {
2323
class HeaderSnapshotFreezer : public SnapshotFreezer {
2424
public:
2525
~HeaderSnapshotFreezer() override = default;
26-
void copy(ROTxn& txn, BlockNumRange range, snapshots::SnapshotFileWriter& file_writer) const override;
26+
void copy(ROTxn& txn, const FreezerCommand& command, snapshots::SnapshotFileWriter& file_writer) const override;
2727
void cleanup(RWTxn& txn, BlockNumRange range) const override;
2828
};
2929

silkworm/db/snapshot_freezer.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,27 @@
1818

1919
#include <silkworm/core/common/base.hpp>
2020

21+
#include "data_migration_command.hpp"
2122
#include "mdbx/mdbx.hpp"
2223
#include "snapshots/snapshot_writer.hpp"
2324

2425
namespace silkworm::db {
2526

27+
struct FreezerCommand : public DataMigrationCommand {
28+
BlockNumRange range;
29+
uint64_t base_txn_id;
30+
31+
FreezerCommand(BlockNumRange range1, uint64_t base_txn_id1)
32+
: range(std::move(range1)),
33+
base_txn_id(base_txn_id1) {}
34+
~FreezerCommand() override = default;
35+
};
36+
2637
struct SnapshotFreezer {
2738
virtual ~SnapshotFreezer() = default;
2839

2940
//! Copies data for a block range from db to the snapshot file.
30-
virtual void copy(ROTxn& txn, BlockNumRange range, snapshots::SnapshotFileWriter& file_writer) const = 0;
41+
virtual void copy(ROTxn& txn, const FreezerCommand& command, snapshots::SnapshotFileWriter& file_writer) const = 0;
3142

3243
//! Cleans up data for a block range from db after it was copied to the snapshot file.
3344
virtual void cleanup(RWTxn& txn, BlockNumRange range) const = 0;

0 commit comments

Comments
 (0)