pageserver: add LayerVisibility

This commit is contained in:
John Spray
2024-06-29 21:50:59 +01:00
parent b874f1dc94
commit b9f1fa5edb
3 changed files with 38 additions and 1 deletions

View File

@@ -457,6 +457,26 @@ pub enum ValueReconstructResult {
Missing,
}
#[derive(Debug, Clone)]
pub(crate) enum LayerVisibility {
/// A Visible layer might be read while serving a read, because there is not an image layer between it
/// and a readable LSN (the tip of the branch or a child's branch point)
Visible,
/// A Covered layer probably won't be read right now, but _can_ be read in future if someone creates
/// a branch or ephemeral endpoint at an LSN below the layer that covers this.
Covered,
/// Calculating layer visibilty requires I/O, so until this has happened layers are loaded
/// in this state. Note that newly written layers may be called Visible immediately, this uninitialized
/// state is for when existing layers are constructed while loading a timeline.
Uninitialized,
}
impl Default for LayerVisibility {
fn default() -> Self {
Self::Uninitialized
}
}
#[derive(Debug)]
pub struct LayerAccessStats(Mutex<LayerAccessStatsLocked>);
@@ -468,6 +488,7 @@ pub struct LayerAccessStats(Mutex<LayerAccessStatsLocked>);
struct LayerAccessStatsLocked {
for_scraping_api: LayerAccessStatsInner,
for_eviction_policy: LayerAccessStatsInner,
visibility: LayerVisibility,
}
impl LayerAccessStatsLocked {
@@ -591,7 +612,13 @@ impl LayerAccessStats {
inner.count_by_access_kind[access_kind] += 1;
inner.task_kind_flag |= ctx.task_kind();
inner.last_accesses.write(this_access);
})
});
// We may access a layer marked as Covered, if a new branch was created that depends on
// this layer, and background updates to layer visibility didn't notice it yet
if !matches!(locked.visibility, LayerVisibility::Visible) {
locked.visibility = LayerVisibility::Visible;
}
}
fn as_api_model(

View File

@@ -250,6 +250,8 @@ impl Layer {
LayerResidenceStatus::Resident,
LayerResidenceEventReason::LayerCreate,
);
// Newly created layers are marked visible by default: the usual case is that they were created to be read.
access_stats.set_visibility(super::LayerVisibility::Visible);
let local_path = local_layer_path(
conf,

View File

@@ -255,6 +255,14 @@ impl LayerManager {
new_layer.layer_desc().lsn_range
);
// Transfer visibilty hint from old to new layer, since the new layer covers the same key space. This is not guaranteed to
// be accurate (as the new layer may cover a different subset of the key range), but is a sensible default, and prevents
// always marking rewritten layers as visible.
new_layer
.as_ref()
.access_stats()
.set_visibility(old_layer.access_stats().get_visibility());
// Safety: we may never rewrite the same file in-place. Callers are responsible
// for ensuring that they only rewrite layers after something changes the path,
// such as an increment in the generation number.