use super::StorageEngine;
use crate::observability::partition_access::{self, AccessWeightBuilder};
#[cfg(not(feature = "tombstones"))]
use crate::storage::sstable::reader::partition_successor::PartitionResidency;
use crate::types::{RowKey, ScanRow, TableId};
use crate::Result;
impl StorageEngine {
pub(crate) async fn scan_partition_recorded(
&self,
table_id: &TableId,
partition_key: &[u8],
schema: Option<&crate::schema::TableSchema>,
) -> Result<(Vec<(RowKey, ScanRow)>, bool)> {
let generations = self.snapshot_for_probe(table_id).await;
let outcome = self
.sstables
.scan_partition(table_id, partition_key, schema)
.await;
if outcome.is_ok() {
Self::record_access_if_enabled(generations, table_id, partition_key).await;
}
outcome
}
pub(crate) async fn scan_partition_with_cell_metadata_recorded(
&self,
table_id: &TableId,
partition_key: &[u8],
schema: Option<&crate::schema::TableSchema>,
) -> Result<(
Vec<(
RowKey,
ScanRow,
std::collections::HashMap<String, crate::types::CellWriteMetadata>,
)>,
bool,
)> {
let generations = self.snapshot_for_probe(table_id).await;
let outcome = self
.sstables
.scan_partition_with_cell_metadata(table_id, partition_key, schema)
.await;
if outcome.is_ok() {
Self::record_access_if_enabled(generations, table_id, partition_key).await;
}
outcome
}
#[cfg(not(feature = "tombstones"))]
pub(crate) async fn scan_partition_clustering_recorded(
&self,
table_id: &TableId,
partition_key: &[u8],
clustering: Option<&crate::storage::sstable::reader::ClusteringSlice>,
schema: Option<&crate::schema::TableSchema>,
) -> Result<(Vec<(RowKey, ScanRow)>, bool)> {
let generations = self.snapshot_for_probe(table_id).await;
let outcome = self
.sstables
.scan_partition_clustering(table_id, partition_key, clustering, schema)
.await;
if outcome.is_ok() {
Self::record_access_if_enabled(generations, table_id, partition_key).await;
}
outcome
}
#[cfg(not(feature = "tombstones"))]
pub(crate) async fn scan_partition_clustering_reverse_recorded(
&self,
table_id: &TableId,
partition_key: &[u8],
schema: Option<&crate::schema::TableSchema>,
) -> Result<Option<Vec<(RowKey, ScanRow)>>> {
let generations = self.snapshot_for_probe(table_id).await;
let outcome = self
.sstables
.scan_partition_clustering_reverse(table_id, partition_key, schema)
.await;
if matches!(outcome, Ok(Some(_))) {
Self::record_access_if_enabled(generations, table_id, partition_key).await;
}
outcome
}
async fn snapshot_for_probe(
&self,
table_id: &TableId,
) -> Option<Vec<std::sync::Arc<crate::storage::sstable::reader::SSTableReader>>> {
if !partition_access::enabled() {
return None;
}
let (readers, _fully_qualified_match) =
self.sstables.resolve_reader_snapshot(table_id).await;
Some(readers)
}
async fn record_access_if_enabled(
generations: Option<Vec<std::sync::Arc<crate::storage::sstable::reader::SSTableReader>>>,
table_id: &TableId,
partition_key: &[u8],
) {
let Some(readers) = generations else {
return;
};
let mut weight = AccessWeightBuilder::new();
for reader in &readers {
Self::note_reader_contribution(reader, partition_key, &mut weight).await;
}
partition_access::record_partition_access(
partition_access::TableScope::from_qualified(table_id.name()),
partition_key,
weight.finish(),
);
}
#[cfg(not(feature = "tombstones"))]
async fn note_reader_contribution(
reader: &std::sync::Arc<crate::storage::sstable::reader::SSTableReader>,
partition_key: &[u8],
weight: &mut AccessWeightBuilder,
) {
match reader.partition_residency(partition_key).await {
PartitionResidency::NotHeld => {}
PartitionResidency::HeldAt(data_offset) => {
match reader.key_cache_get(partition_key) {
Some(loc) if loc.data_size > 0 => weight.note_sized(loc.data_size),
_ => {
Self::note_measured_extent(reader, data_offset, partition_key, weight).await
}
}
}
PartitionResidency::Unknown => weight.note_unsized(),
}
}
#[cfg(feature = "tombstones")]
async fn note_reader_contribution(
_reader: &std::sync::Arc<crate::storage::sstable::reader::SSTableReader>,
_partition_key: &[u8],
weight: &mut AccessWeightBuilder,
) {
weight.note_unsized();
}
#[cfg(not(feature = "tombstones"))]
async fn note_measured_extent(
reader: &std::sync::Arc<crate::storage::sstable::reader::SSTableReader>,
data_offset: u64,
partition_key: &[u8],
weight: &mut AccessWeightBuilder,
) {
match reader
.measure_partition_extent(data_offset, partition_key)
.await
{
Ok(Some(gap)) => weight.note_measured(gap),
Ok(None) => weight.note_unsized(),
Err(e) => {
tracing::debug!(
error = %e,
"partition-access probe could not measure a partition extent; \
recording the access as size_source=unavailable (#2827)"
);
weight.note_unsized();
}
}
}
}