From 56e36f4ecb91f0bf1c8ec81f9639d51df3287956 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 14 Sep 2022 05:34:49 +1000 Subject: [PATCH] Make the FinalizedState cloneable --- zebra-state/src/service.rs | 5 ++++ zebra-state/src/service/finalized_state.rs | 14 ++++++++--- .../src/service/finalized_state/disk_db.rs | 25 ++++++++++++++----- .../src/service/finalized_state/zebra_db.rs | 11 ++++++-- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/zebra-state/src/service.rs b/zebra-state/src/service.rs index cff9478fcd7..18c0ee4ea50 100644 --- a/zebra-state/src/service.rs +++ b/zebra-state/src/service.rs @@ -113,9 +113,14 @@ pub(crate) struct StateService { // Exclusively Writeable State // /// The non-finalized chain state, including its in-memory chain forks. + // + // TODO: get rid of this struct member, and just let the block write task own the NonFinalizedState. mem: NonFinalizedState, /// The finalized chain state, including its on-disk database. + // + // TODO: get rid of this struct member, and just let the ReadStateService + // and block write task share ownership of the database. pub(crate) disk: FinalizedState, // Pending UTXO Request Tracking diff --git a/zebra-state/src/service/finalized_state.rs b/zebra-state/src/service/finalized_state.rs index 11844e96feb..5b6cae48911 100644 --- a/zebra-state/src/service/finalized_state.rs +++ b/zebra-state/src/service/finalized_state.rs @@ -44,10 +44,17 @@ pub use disk_format::{OutputIndex, OutputLocation, TransactionLocation}; pub(super) use zebra_db::ZebraDb; /// The finalized part of the chain state, stored in the db. -#[derive(Debug)] +/// +/// `rocksdb` allows concurrent writes through a shared reference, +/// so finalized state instances are cloneable. When the final clone is dropped, +/// the database is closed. +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FinalizedState { // Configuration // + // This configuration cannot be modified after the database is initialized, + // because some clones would have different values. + // /// The configured network. network: Network, @@ -58,14 +65,13 @@ pub struct FinalizedState { // Owned State // + // Everything contained in this state must be shared by all clones, or read-only. + // /// The underlying database. /// /// `rocksdb` allows reads and writes via a shared reference, /// so this database object can be freely cloned. /// The last instance that is dropped will close the underlying database. - // - // TODO: get rid of this struct member, and just let the [`ReadStateService`] - // and block write task share ownership of the database. db: ZebraDb, } diff --git a/zebra-state/src/service/finalized_state/disk_db.rs b/zebra-state/src/service/finalized_state/disk_db.rs index db7c628ed24..d183b4159be 100644 --- a/zebra-state/src/service/finalized_state/disk_db.rs +++ b/zebra-state/src/service/finalized_state/disk_db.rs @@ -34,6 +34,10 @@ pub type DB = rocksdb::DBWithThreadMode; /// Wrapper struct to ensure low-level database access goes through the correct API. /// +/// `rocksdb` allows concurrent writes through a shared reference, +/// so database instances are cloneable. When the final clone is dropped, +/// the database is closed. +/// /// # Correctness /// /// Reading transactions from the database using RocksDB iterators causes hangs. @@ -48,6 +52,20 @@ pub type DB = rocksdb::DBWithThreadMode; /// (Or it might be fixed by future RocksDB upgrades.) #[derive(Clone, Debug)] pub struct DiskDb { + // Configuration + // + // This configuration cannot be modified after the database is initialized, + // because some clones would have different values. + // + /// The configured temporary database setting. + /// + /// If true, the database files are deleted on drop. + ephemeral: bool, + + // Owned State + // + // Everything contained in this state must be shared by all clones, or read-only. + // /// The shared inner RocksDB database. /// /// RocksDB allows reads and writes via a shared reference. @@ -58,11 +76,6 @@ pub struct DiskDb { /// In [`MultiThreaded`](rocksdb::MultiThreaded) mode, /// only [`Drop`] requires exclusive access. db: Arc, - - /// The configured temporary database setting. - /// - /// If true, the database files are deleted on drop. - ephemeral: bool, } /// Wrapper struct to ensure low-level database writes go through the correct API. @@ -434,8 +447,8 @@ impl DiskDb { info!("Opened Zebra state cache at {}", path.display()); let db = DiskDb { - db: Arc::new(db), ephemeral: config.ephemeral, + db: Arc::new(db), }; db.assert_default_cf_is_empty(); diff --git a/zebra-state/src/service/finalized_state/zebra_db.rs b/zebra-state/src/service/finalized_state/zebra_db.rs index 60bb11389c2..9789e50f577 100644 --- a/zebra-state/src/service/finalized_state/zebra_db.rs +++ b/zebra-state/src/service/finalized_state/zebra_db.rs @@ -28,10 +28,17 @@ pub mod transparent; pub mod arbitrary; /// Wrapper struct to ensure high-level typed database access goes through the correct API. -#[derive(Clone, Debug)] +/// +/// `rocksdb` allows concurrent writes through a shared reference, +/// so database instances are cloneable. When the final clone is dropped, +/// the database is closed. +#[derive(Clone, Debug, Eq, PartialEq)] pub struct ZebraDb { + // Owned State + // + // Everything contained in this state must be shared by all clones, or read-only. + // /// The inner low-level database wrapper for the RocksDB database. - /// This wrapper can be cloned and shared. db: DiskDb, }