diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index 4dca6ba6f..756e4ca2e 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -158,6 +158,7 @@ pub struct Blockstore { block_height_cf: LedgerColumn, program_costs_cf: LedgerColumn, bank_hash_cf: LedgerColumn, + optimistic_slots_cf: LedgerColumn, last_root: RwLock, insert_shreds_lock: Mutex<()>, new_shreds_signals: Mutex>>, @@ -379,6 +380,7 @@ impl Blockstore { let block_height_cf = db.column(); let program_costs_cf = db.column(); let bank_hash_cf = db.column(); + let optimistic_slots_cf = db.column(); let db = Arc::new(db); @@ -430,6 +432,7 @@ impl Blockstore { block_height_cf, program_costs_cf, bank_hash_cf, + optimistic_slots_cf, new_shreds_signals: Mutex::default(), completed_slots_senders: Mutex::default(), shred_timing_point_sender: None, @@ -752,6 +755,7 @@ impl Blockstore { self.block_height_cf.submit_rocksdb_cf_metrics(); self.program_costs_cf.submit_rocksdb_cf_metrics(); self.bank_hash_cf.submit_rocksdb_cf_metrics(); + self.optimistic_slots_cf.submit_rocksdb_cf_metrics(); } fn try_shred_recovery( diff --git a/ledger/src/blockstore/blockstore_purge.rs b/ledger/src/blockstore/blockstore_purge.rs index fad534cef..640b338f2 100644 --- a/ledger/src/blockstore/blockstore_purge.rs +++ b/ledger/src/blockstore/blockstore_purge.rs @@ -211,6 +211,10 @@ impl Blockstore { & self .db .delete_range_cf::(&mut write_batch, from_slot, to_slot) + .is_ok() + & self + .db + .delete_range_cf::(&mut write_batch, from_slot, to_slot) .is_ok(); let mut w_active_transaction_status_index = self.active_transaction_status_index.write().unwrap(); @@ -328,6 +332,10 @@ impl Blockstore { && self .block_height_cf .compact_range(from_slot, to_slot) + .unwrap_or(false) + && self + .optimistic_slots_cf + .compact_range(from_slot, to_slot) .unwrap_or(false); compact_timer.stop(); if !result { diff --git a/ledger/src/blockstore_db.rs b/ledger/src/blockstore_db.rs index 2851e3acb..4dcdab9bc 100644 --- a/ledger/src/blockstore_db.rs +++ b/ledger/src/blockstore_db.rs @@ -104,6 +104,8 @@ const PERF_SAMPLES_CF: &str = "perf_samples"; const BLOCK_HEIGHT_CF: &str = "block_height"; /// Column family for ProgramCosts const PROGRAM_COSTS_CF: &str = "program_costs"; +/// Column family for optimistic slots +const OPTIMISTIC_SLOTS_CF: &str = "optimistic_slots"; // 1 day is chosen for the same reasoning of DEFAULT_COMPACTION_SLOT_INTERVAL const PERIODIC_COMPACTION_SECONDS: u64 = 60 * 60 * 24; @@ -222,6 +224,10 @@ pub mod columns { /// The program costs column pub struct ProgramCosts; + #[derive(Debug)] + /// The optimistic slot column + pub struct OptimisticSlots; + // When adding a new column ... // - Add struct below and implement `Column` and `ColumnName` traits // - Add descriptor in Rocks::cf_descriptors() and name in Rocks::columns() @@ -453,6 +459,7 @@ impl Rocks { new_cf_descriptor::(options, oldest_slot), new_cf_descriptor::(options, oldest_slot), new_cf_descriptor::(options, oldest_slot), + new_cf_descriptor::(options, oldest_slot), ] } @@ -479,6 +486,7 @@ impl Rocks { PerfSamples::NAME, BlockHeight::NAME, ProgramCosts::NAME, + OptimisticSlots::NAME, ] } @@ -984,6 +992,14 @@ impl TypedColumn for columns::ErasureMeta { type Type = blockstore_meta::ErasureMeta; } +impl SlotColumn for columns::OptimisticSlots {} +impl ColumnName for columns::OptimisticSlots { + const NAME: &'static str = OPTIMISTIC_SLOTS_CF; +} +impl TypedColumn for columns::OptimisticSlots { + type Type = blockstore_meta::OptimisticSlotMetaVersioned; +} + #[derive(Debug)] pub struct Database { backend: Arc, diff --git a/ledger/src/blockstore_meta.rs b/ledger/src/blockstore_meta.rs index dd7877ac4..885a1f4f9 100644 --- a/ledger/src/blockstore_meta.rs +++ b/ledger/src/blockstore_meta.rs @@ -1,7 +1,10 @@ use { crate::shred::{Shred, ShredType}, serde::{Deserialize, Deserializer, Serialize, Serializer}, - solana_sdk::{clock::Slot, hash::Hash}, + solana_sdk::{ + clock::{Slot, UnixTimestamp}, + hash::Hash, + }, std::{ collections::BTreeSet, ops::{Range, RangeBounds}, @@ -327,6 +330,34 @@ pub struct ProgramCost { pub cost: u64, } +#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)] +pub struct OptimisticSlotMetaV0 { + pub hash: Hash, + pub timestamp: UnixTimestamp, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq)] +pub enum OptimisticSlotMetaVersioned { + V0(OptimisticSlotMetaV0), +} + +impl OptimisticSlotMetaVersioned { + pub fn new(hash: Hash, timestamp: UnixTimestamp) -> Self { + OptimisticSlotMetaVersioned::V0(OptimisticSlotMetaV0 { hash, timestamp }) + } + + pub fn hash(&self) -> Hash { + match self { + OptimisticSlotMetaVersioned::V0(meta) => meta.hash, + } + } + + pub fn timestamp(&self) -> UnixTimestamp { + match self { + OptimisticSlotMetaVersioned::V0(meta) => meta.timestamp, + } + } +} #[cfg(test)] mod test { use { diff --git a/ledger/src/blockstore_metrics.rs b/ledger/src/blockstore_metrics.rs index 1eba08ba0..41ea5815a 100644 --- a/ledger/src/blockstore_metrics.rs +++ b/ledger/src/blockstore_metrics.rs @@ -1138,6 +1138,42 @@ impl ColumnMetrics for columns::BankHash { } } +impl ColumnMetrics for columns::OptimisticSlots { + fn report_cf_metrics( + cf_metrics: BlockstoreRocksDbColumnFamilyMetrics, + column_options: &Arc, + ) { + cf_metrics.report_metrics(rocksdb_metric_header!( + "blockstore_rocksdb_cfs", + "optimistic_slots", + column_options + )); + } + fn rocksdb_get_perf_metric_header(column_options: &Arc) -> &'static str { + rocksdb_metric_header!( + "blockstore_rocksdb_read_perf,op=get", + "optimistic_slots", + column_options + ) + } + fn rocksdb_put_perf_metric_header(column_options: &Arc) -> &'static str { + rocksdb_metric_header!( + "blockstore_rocksdb_write_perf,op=put", + "optimistic_slots", + column_options + ) + } + fn rocksdb_delete_perf_metric_header( + column_options: &Arc, + ) -> &'static str { + rocksdb_metric_header!( + "blockstore_rocksdb_write_perf,op=delete", + "optimistic_slots", + column_options + ) + } +} + impl ColumnMetrics for columns::Root { fn report_cf_metrics( cf_metrics: BlockstoreRocksDbColumnFamilyMetrics,