diff --git a/pageserver/src/tenant/storage_layer/layer.rs b/pageserver/src/tenant/storage_layer/layer.rs index 759f6d664c..13a619ddf1 100644 --- a/pageserver/src/tenant/storage_layer/layer.rs +++ b/pageserver/src/tenant/storage_layer/layer.rs @@ -8,6 +8,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Weak}; use std::time::SystemTime; use tracing::Instrument; +use utils::id::{TenantId, TimelineId}; use utils::lsn::Lsn; use utils::sync::heavier_once_cell; @@ -82,7 +83,38 @@ impl Layer { let owner = Layer(Arc::new(LayerInner::new( conf, - timeline, + Arc::downgrade(timeline), + access_stats, + desc, + None, + metadata.generation, + ))); + + debug_assert!(owner.0.needs_download_blocking().unwrap().is_some()); + + owner + } + + /// A layer which is resident locally in a secondary location: not associated with a live Timeline object. + pub(crate) fn for_secondary( + conf: &'static PageServerConf, + tenant_id: &TenantId, + timeline_id: &TimelineId, + file_name: LayerFileName, + metadata: LayerFileMetadata, + ) -> Self { + let desc = PersistentLayerDesc::from_filename( + *tenant_id, + *timeline_id, + file_name, + metadata.file_size(), + ); + + let access_stats = LayerAccessStats::for_loading_layer(LayerResidenceStatus::Evicted); + + let owner = Layer(Arc::new(LayerInner::new( + conf, + Weak::default(), access_stats, desc, None, @@ -121,7 +153,7 @@ impl Layer { LayerInner::new( conf, - timeline, + Arc::downgrade(timeline), access_stats, desc, Some(inner), @@ -163,7 +195,7 @@ impl Layer { ); LayerInner::new( conf, - timeline, + Arc::downgrade(timeline), access_stats, desc, Some(inner), @@ -496,22 +528,27 @@ impl Drop for LayerInner { impl LayerInner { fn new( conf: &'static PageServerConf, - timeline: &Arc, + timeline: Weak, access_stats: LayerAccessStats, desc: PersistentLayerDesc, downloaded: Option>, generation: Generation, ) -> Self { let path = conf - .timeline_path(&timeline.tenant_id, &timeline.timeline_id) + .timeline_path(&desc.tenant_id, &desc.timeline_id) .join(desc.filename().to_string()); + let have_remote_client = timeline + .upgrade() + .map(|t| t.remote_client.is_some()) + .unwrap_or(false); + LayerInner { conf, path, desc, - timeline: Arc::downgrade(timeline), - have_remote_client: timeline.remote_client.is_some(), + timeline, + have_remote_client, access_stats, wanted_garbage_collected: AtomicBool::new(false), wanted_evicted: AtomicBool::new(false),