use alloc::sync::Arc;
use crate::db::CompactionProgress;
use crate::ivfpq::index::TrainProgress;
#[derive(Debug, Clone)]
pub struct CommitInfo {
pub transaction_id: u64,
pub dirty_page_count: u64,
pub two_phase: bool,
#[cfg(feature = "std")]
pub commit_duration: core::time::Duration,
}
pub trait DatabaseObserver: Send + Sync + 'static {
fn on_write_commit(&self, _info: &CommitInfo) {}
fn on_write_abort(&self, _transaction_id: u64) {}
fn on_read_begin(&self, _transaction_id: u64) {}
fn on_read_end(&self, _transaction_id: u64) {}
fn on_compaction_step(&self, _progress: &CompactionProgress) {}
fn on_compaction_complete(&self, _total_pages_relocated: u64) {}
fn on_train_progress(&self, _index_name: &str, _progress: &TrainProgress) {}
fn on_blob_write(&self, _blob_id: u64, _size_bytes: u64) {}
fn on_blob_dedup(&self, _blob_id: u64, _saved_bytes: u64) {}
fn on_checksum_failure(&self, _page_number: u64) {}
}
pub(crate) struct NoopObserver;
impl DatabaseObserver for NoopObserver {}
pub(crate) fn default_observer() -> Arc<dyn DatabaseObserver> {
Arc::new(NoopObserver)
}
#[cfg(feature = "metrics")]
pub struct DbMetrics {
pub(crate) write_txn_committed: portable_atomic::AtomicU64,
pub(crate) write_txn_aborted: portable_atomic::AtomicU64,
pub(crate) read_txn_opened: portable_atomic::AtomicU64,
pub(crate) read_txn_closed: portable_atomic::AtomicU64,
pub(crate) pages_allocated: portable_atomic::AtomicU64,
pub(crate) pages_freed: portable_atomic::AtomicU64,
pub(crate) bytes_written_logical: portable_atomic::AtomicU64,
pub(crate) bytes_written_physical: portable_atomic::AtomicU64,
pub(crate) blob_writes: portable_atomic::AtomicU64,
pub(crate) blob_dedup_hits: portable_atomic::AtomicU64,
pub(crate) vector_searches: portable_atomic::AtomicU64,
pub(crate) compaction_pages_relocated: portable_atomic::AtomicU64,
}
#[cfg(feature = "metrics")]
impl DbMetrics {
pub(crate) fn new() -> Self {
Self {
write_txn_committed: portable_atomic::AtomicU64::new(0),
write_txn_aborted: portable_atomic::AtomicU64::new(0),
read_txn_opened: portable_atomic::AtomicU64::new(0),
read_txn_closed: portable_atomic::AtomicU64::new(0),
pages_allocated: portable_atomic::AtomicU64::new(0),
pages_freed: portable_atomic::AtomicU64::new(0),
bytes_written_logical: portable_atomic::AtomicU64::new(0),
bytes_written_physical: portable_atomic::AtomicU64::new(0),
blob_writes: portable_atomic::AtomicU64::new(0),
blob_dedup_hits: portable_atomic::AtomicU64::new(0),
vector_searches: portable_atomic::AtomicU64::new(0),
compaction_pages_relocated: portable_atomic::AtomicU64::new(0),
}
}
pub fn write_txn_committed(&self) -> u64 {
self.write_txn_committed
.load(portable_atomic::Ordering::Relaxed)
}
pub fn write_txn_aborted(&self) -> u64 {
self.write_txn_aborted
.load(portable_atomic::Ordering::Relaxed)
}
pub fn read_txn_opened(&self) -> u64 {
self.read_txn_opened
.load(portable_atomic::Ordering::Relaxed)
}
pub fn read_txn_closed(&self) -> u64 {
self.read_txn_closed
.load(portable_atomic::Ordering::Relaxed)
}
pub fn pages_allocated(&self) -> u64 {
self.pages_allocated
.load(portable_atomic::Ordering::Relaxed)
}
pub fn pages_freed(&self) -> u64 {
self.pages_freed.load(portable_atomic::Ordering::Relaxed)
}
pub fn bytes_written_logical(&self) -> u64 {
self.bytes_written_logical
.load(portable_atomic::Ordering::Relaxed)
}
pub fn bytes_written_physical(&self) -> u64 {
self.bytes_written_physical
.load(portable_atomic::Ordering::Relaxed)
}
pub fn blob_writes(&self) -> u64 {
self.blob_writes.load(portable_atomic::Ordering::Relaxed)
}
pub fn blob_dedup_hits(&self) -> u64 {
self.blob_dedup_hits
.load(portable_atomic::Ordering::Relaxed)
}
pub fn vector_searches(&self) -> u64 {
self.vector_searches
.load(portable_atomic::Ordering::Relaxed)
}
pub fn compaction_pages_relocated(&self) -> u64 {
self.compaction_pages_relocated
.load(portable_atomic::Ordering::Relaxed)
}
}
#[cfg(feature = "metrics")]
impl core::fmt::Debug for DbMetrics {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("DbMetrics")
.field("write_txn_committed", &self.write_txn_committed())
.field("write_txn_aborted", &self.write_txn_aborted())
.field("read_txn_opened", &self.read_txn_opened())
.field("read_txn_closed", &self.read_txn_closed())
.field("pages_allocated", &self.pages_allocated())
.field("pages_freed", &self.pages_freed())
.field("bytes_written_logical", &self.bytes_written_logical())
.field("bytes_written_physical", &self.bytes_written_physical())
.field("blob_writes", &self.blob_writes())
.field("blob_dedup_hits", &self.blob_dedup_hits())
.field("vector_searches", &self.vector_searches())
.field(
"compaction_pages_relocated",
&self.compaction_pages_relocated(),
)
.finish()
}
}