1212#include < utility>
1313#include < vector>
1414
15- #include < absl/strings/str_split.h>
1615#include < boost/thread/scoped_thread.hpp>
1716#include < gsl/util>
1817#include < nlohmann/json.hpp>
2625#include < silkworm/db/blocks/schema_config.hpp>
2726#include < silkworm/db/blocks/transactions/txn_to_block_index.hpp>
2827#include < silkworm/db/buffer.hpp>
28+ #include < silkworm/db/capi/component.hpp>
29+ #include < silkworm/db/datastore/kvdb/mdbx_version.hpp>
2930#include < silkworm/db/datastore/snapshots/index_builder.hpp>
3031#include < silkworm/db/datastore/snapshots/segment/segment_reader.hpp>
3132#include < silkworm/db/stages.hpp>
@@ -67,36 +68,6 @@ struct ExecutionProgress {
6768 float batch_progress_perc{0.0 };
6869};
6970
70- // ! Kind of match to perform between Erigon and Silkworm libmdbx versions
71- enum class MdbxVersionCheck : uint8_t {
72- kNone , // / no check at all
73- kExact , // / git-describe versions must match perfectly
74- kSemantic , // / compare semantic versions (<M1.m1.p1> == <M2.m2.p2>)
75- };
76-
77- static bool is_compatible_mdbx_version (std::string_view their_version, std::string_view our_version, MdbxVersionCheck check) {
78- SILK_TRACE << " is_compatible_mdbx_version their_version: " << their_version << " our_version: " << our_version;
79- bool compatible{false };
80- switch (check) {
81- case MdbxVersionCheck::kNone : {
82- compatible = true ;
83- } break ;
84- case MdbxVersionCheck::kExact : {
85- compatible = their_version == our_version;
86- } break ;
87- case MdbxVersionCheck::kSemantic : {
88- const std::vector<std::string> their_version_parts = absl::StrSplit (std::string (their_version), ' .' );
89- const std::vector<std::string> our_version_parts = absl::StrSplit (std::string (our_version), ' .' );
90- compatible = (their_version_parts.size () >= 3 ) &&
91- (our_version_parts.size () >= 3 ) &&
92- (their_version_parts[0 ] == our_version_parts[0 ]) &&
93- (their_version_parts[1 ] == our_version_parts[1 ]) &&
94- (their_version_parts[2 ] == our_version_parts[2 ]);
95- }
96- }
97- return compatible;
98- }
99-
10071// ! Generate log arguments for Silkworm library version
10172static log::Args log_args_for_version () {
10273 const auto build_info{silkworm_get_buildinfo ()};
@@ -191,6 +162,8 @@ class SignalHandlerGuard {
191162static bool is_initialized{false };
192163
193164SILKWORM_EXPORT int silkworm_init (SilkwormHandle* handle, const struct SilkwormSettings * settings) SILKWORM_NOEXCEPT {
165+ using namespace datastore ::kvdb;
166+
194167 if (!handle) {
195168 return SILKWORM_INVALID_HANDLE;
196169 }
@@ -235,14 +208,17 @@ SILKWORM_EXPORT int silkworm_init(SilkwormHandle* handle, const struct SilkwormS
235208 snapshots_dir_path,
236209 /* open = */ false ,
237210 settings->state_repo_index_salt );
211+ db::capi::Component db{
212+ .blocks_repository = std::move (blocks_repository),
213+ .state_repository_latest = std::move (state_repository_latest),
214+ .state_repository_historical = std::move (state_repository_historical),
215+ .chaindata = {},
216+ };
238217
239218 // NOLINTNEXTLINE(bugprone-unhandled-exception-at-new)
240- *handle = new ::SilkwormInstance{
241- .blocks_repository = std::make_unique<snapshots::SnapshotRepository>(std::move (blocks_repository)),
242- .state_repository_latest = std::make_unique<snapshots::SnapshotRepository>(std::move (state_repository_latest)),
243- .state_repository_historical = std::make_unique<snapshots::SnapshotRepository>(std::move (state_repository_historical)),
244- };
219+ *handle = new ::SilkwormInstance{};
245220 (*handle)->common = std::move (common);
221+ (*handle)->db = std::make_unique<db::capi::Component>(std::move (db));
246222
247223 log::Info{" Silkworm build info" , log_args_for_version ()}; // NOLINT(*-unused-raii)
248224
@@ -255,10 +231,6 @@ SILKWORM_EXPORT int silkworm_init(SilkwormHandle* handle, const struct SilkwormS
255231 return SILKWORM_OK;
256232}
257233
258- SILKWORM_EXPORT const char * silkworm_libmdbx_version () SILKWORM_NOEXCEPT {
259- return ::mdbx::get_version ().git .describe ;
260- }
261-
262234class BlockProvider {
263235 static constexpr size_t kTxnRefreshThreshold {100 };
264236
@@ -348,8 +320,9 @@ int silkworm_execute_blocks_ephemeral(SilkwormHandle handle, MDBX_txn* mdbx_txn,
348320
349321 try {
350322 auto txn = datastore::kvdb::RWTxnUnmanaged{mdbx_txn};
323+ db::DataModel da_layer{txn, handle->db ->blocks_repository };
351324
352- db::Buffer state_buffer{txn, std::make_unique<db::BufferFullDataModel>(db::DataModel{txn, *handle-> blocks_repository } )};
325+ db::Buffer state_buffer{txn, std::make_unique<db::BufferFullDataModel>(da_layer )};
353326 state_buffer.set_memory_limit (batch_size);
354327
355328 const size_t max_batch_size{batch_size};
@@ -358,7 +331,6 @@ int silkworm_execute_blocks_ephemeral(SilkwormHandle handle, MDBX_txn* mdbx_txn,
358331 BlockNum block_num{start_block};
359332 BlockNum batch_start_block_num{start_block};
360333 BlockNum last_block_num = 0 ;
361- db::DataModel da_layer{txn, *handle->blocks_repository };
362334
363335 AnalysisCache analysis_cache{execution::block::BlockExecutor::kDefaultAnalysisCacheSize };
364336 execution::block::BlockExecutor block_executor{*chain_info, write_receipts, write_call_traces, write_change_sets};
@@ -464,29 +436,22 @@ int silkworm_execute_blocks_perpetual(SilkwormHandle handle, MDBX_env* mdbx_env,
464436
465437 try {
466438 // Wrap MDBX env into an internal *unmanaged* env, i.e. MDBX env is only used but its lifecycle is untouched
467- datastore::kvdb::EnvUnmanaged unmanaged_env{mdbx_env};
468- const auto env_path = unmanaged_env.get_path ();
469- handle->chaindata = std::make_unique<datastore::kvdb::DatabaseUnmanaged>(
470- db::DataStore::make_chaindata_database (std::move (unmanaged_env)));
471- auto & chaindata = *handle->chaindata ;
439+ if (!handle->db ->chaindata ) {
440+ handle->db ->chaindata = std::make_unique<datastore::kvdb::DatabaseUnmanaged>(
441+ db::DataStore::make_chaindata_database (datastore::kvdb::EnvUnmanaged{mdbx_env}));
442+ }
443+ auto & chaindata = *handle->db ->chaindata ;
444+ db::DataModelFactory data_model_factory = handle->db ->data_model_factory ();
472445
473446 datastore::kvdb::RWAccess rw_access = chaindata.access_rw ();
474447 auto txn = rw_access.start_rw_tx ();
475448
476- db::Buffer state_buffer{txn, std::make_unique<db::BufferFullDataModel>(db::DataModel{ txn, *handle-> blocks_repository } )};
449+ db::Buffer state_buffer{txn, std::make_unique<db::BufferFullDataModel>(data_model_factory ( txn) )};
477450 state_buffer.set_memory_limit (batch_size);
478451
479452 BoundedBuffer<std::optional<Block>> block_buffer{kMaxBlockBufferSize };
480453 [[maybe_unused]] auto _ = gsl::finally ([&block_buffer] { block_buffer.terminate_and_release_all (); });
481454
482- db::DataStoreRef data_store{
483- chaindata.ref (),
484- *handle->blocks_repository ,
485- *handle->state_repository_latest ,
486- *handle->state_repository_historical ,
487- };
488- db::DataModelFactory data_model_factory{std::move (data_store)};
489-
490455 BlockProvider block_provider{
491456 &block_buffer,
492457 chaindata.access_ro (),
@@ -556,7 +521,7 @@ int silkworm_execute_blocks_perpetual(SilkwormHandle handle, MDBX_env* mdbx_env,
556521 txn.commit_and_renew ();
557522 const auto elapsed_time_and_duration = sw.stop ();
558523 log::Info (" [4/12 Execution] Commit state+history" , // NOLINT(*-unused-raii)
559- log_args_for_exec_commit (elapsed_time_and_duration.second , env_path ));
524+ log_args_for_exec_commit (elapsed_time_and_duration.second , (*rw_access). get_path () ));
560525
561526 if (last_executed_block) {
562527 *last_executed_block = last_block_num;
@@ -600,13 +565,8 @@ SILKWORM_EXPORT int silkworm_execute_txn(SilkwormHandle handle, MDBX_txn* mdbx_t
600565 *blob_gas_used = 0 ;
601566 }
602567
603- if (!handle->blocks_repository ) {
604- SILK_ERROR << " Blocks repository not found" ;
605- return SILKWORM_INVALID_HANDLE;
606- }
607-
608- if (!handle->state_repository_latest ) {
609- SILK_ERROR << " State repository latest not found" ;
568+ if (!handle->db ) {
569+ SILK_ERROR << " Database component not initialized" ;
610570 return SILKWORM_INVALID_HANDLE;
611571 }
612572
@@ -625,8 +585,8 @@ SILKWORM_EXPORT int silkworm_execute_txn(SilkwormHandle handle, MDBX_txn* mdbx_t
625585 txn_id,
626586 unmanaged_tx,
627587 db_ref,
628- * handle->blocks_repository ,
629- * handle->state_repository_latest ,
588+ handle-> db ->blocks_repository ,
589+ handle-> db ->state_repository_latest ,
630590 };
631591 if (!handle->chain_config ) {
632592 handle->chain_config = db::read_chain_config (unmanaged_tx);
@@ -771,8 +731,8 @@ SILKWORM_EXPORT int silkworm_block_exec_end(SilkwormHandle handle, MDBX_txn* mdb
771731 txn_id,
772732 unmanaged_tx,
773733 db_ref,
774- * handle->blocks_repository ,
775- * handle->state_repository_latest ,
734+ handle-> db ->blocks_repository ,
735+ handle-> db ->state_repository_latest ,
776736 };
777737
778738 const auto log_index = handle->executions_in_block [index].log_index ;
@@ -787,9 +747,6 @@ SILKWORM_EXPORT int silkworm_fini(SilkwormHandle handle) SILKWORM_NOEXCEPT {
787747 if (!handle) {
788748 return SILKWORM_INVALID_HANDLE;
789749 }
790- if (!handle->blocks_repository ) {
791- return SILKWORM_INVALID_HANDLE;
792- }
793750 delete handle;
794751
795752 is_initialized = false ;
0 commit comments