diff --git a/pageserver/src/tenant/layer_map.rs b/pageserver/src/tenant/layer_map.rs index 844f117ea2..707233b003 100644 --- a/pageserver/src/tenant/layer_map.rs +++ b/pageserver/src/tenant/layer_map.rs @@ -464,7 +464,7 @@ impl LayerMap { pub(self) fn insert_historic_noflush(&mut self, layer_desc: PersistentLayerDesc) { // TODO: See #3869, resulting #4088, attempted fix and repro #4094 - if Self::is_l0(&layer_desc.key_range) { + if Self::is_l0(&layer_desc.key_range, layer_desc.is_delta) { self.l0_delta_layers.push(layer_desc.clone().into()); } @@ -483,7 +483,7 @@ impl LayerMap { self.historic .remove(historic_layer_coverage::LayerKey::from(layer_desc)); let layer_key = layer_desc.key(); - if Self::is_l0(&layer_desc.key_range) { + if Self::is_l0(&layer_desc.key_range, layer_desc.is_delta) { let len_before = self.l0_delta_layers.len(); let mut l0_delta_layers = std::mem::take(&mut self.l0_delta_layers); l0_delta_layers.retain(|other| other.key() != layer_key); @@ -600,8 +600,8 @@ impl LayerMap { } /// Check if the key range resembles that of an L0 layer. - pub fn is_l0(key_range: &Range) -> bool { - key_range == &(Key::MIN..Key::MAX) + pub fn is_l0(key_range: &Range, is_delta_layer: bool) -> bool { + is_delta_layer && key_range == &(Key::MIN..Key::MAX) } /// This function determines which layers are counted in `count_deltas`: @@ -628,7 +628,7 @@ impl LayerMap { /// than just the current partition_range. pub fn is_reimage_worthy(layer: &PersistentLayerDesc, partition_range: &Range) -> bool { // Case 1 - if !Self::is_l0(&layer.key_range) { + if !Self::is_l0(&layer.key_range, layer.is_delta) { return true; } diff --git a/pageserver/src/tenant/storage_layer/layer.rs b/pageserver/src/tenant/storage_layer/layer.rs index 774f97e1d9..2607b574e7 100644 --- a/pageserver/src/tenant/storage_layer/layer.rs +++ b/pageserver/src/tenant/storage_layer/layer.rs @@ -1296,7 +1296,10 @@ impl LayerInner { lsn_end: lsn_range.end, remote: !resident, access_stats, - l0: crate::tenant::layer_map::LayerMap::is_l0(&self.layer_desc().key_range), + l0: crate::tenant::layer_map::LayerMap::is_l0( + &self.layer_desc().key_range, + self.layer_desc().is_delta, + ), } } else { let lsn = self.desc.image_layer_lsn(); diff --git a/pageserver/src/tenant/storage_layer/layer_name.rs b/pageserver/src/tenant/storage_layer/layer_name.rs index f33ca076ab..47ae556279 100644 --- a/pageserver/src/tenant/storage_layer/layer_name.rs +++ b/pageserver/src/tenant/storage_layer/layer_name.rs @@ -256,6 +256,10 @@ impl LayerName { LayerName::Delta(layer) => &layer.key_range, } } + + pub fn is_delta(&self) -> bool { + matches!(self, LayerName::Delta(_)) + } } impl fmt::Display for LayerName { diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index dc9cddea43..b33e436fce 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -3002,7 +3002,10 @@ impl Timeline { // - For L1 & image layers, download most recent LSNs first: the older the LSN, the sooner // the layer is likely to be covered by an image layer during compaction. layers.sort_by_key(|(desc, _meta, _atime)| { - std::cmp::Reverse((!LayerMap::is_l0(&desc.key_range), desc.lsn_range.end)) + std::cmp::Reverse(( + !LayerMap::is_l0(&desc.key_range, desc.is_delta), + desc.lsn_range.end, + )) }); let layers = layers @@ -4585,7 +4588,7 @@ impl Timeline { // for compact_level0_phase1 creating an L0, which does not happen in practice // because we have not implemented L0 => L0 compaction. duplicated_layers.insert(l.layer_desc().key()); - } else if LayerMap::is_l0(&l.layer_desc().key_range) { + } else if LayerMap::is_l0(&l.layer_desc().key_range, l.layer_desc().is_delta) { return Err(CompactionError::Other(anyhow::anyhow!("compaction generates a L0 layer file as output, which will cause infinite compaction."))); } else { insert_layers.push(l.clone()); @@ -5877,7 +5880,7 @@ mod tests { }; // Apart from L0s, newest Layers should come first - if !LayerMap::is_l0(layer.name.key_range()) { + if !LayerMap::is_l0(layer.name.key_range(), layer.name.is_delta()) { assert!(layer_lsn <= last_lsn); last_lsn = layer_lsn; } diff --git a/storage_scrubber/src/checks.rs b/storage_scrubber/src/checks.rs index b35838bcf7..08b0f06ebf 100644 --- a/storage_scrubber/src/checks.rs +++ b/storage_scrubber/src/checks.rs @@ -150,7 +150,7 @@ pub(crate) async fn branch_cleanup_and_check_errors( if response.is_err() { // Object is not present. - let is_l0 = LayerMap::is_l0(layer.key_range()); + let is_l0 = LayerMap::is_l0(layer.key_range(), layer.is_delta()); let msg = format!( "index_part.json contains a layer {}{} (shard {}) that is not present in remote storage (layer_is_l0: {})",