From 9ce6e7c86bde0bea1d8f862bc4b443a2f3eca105 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Fri, 16 Jun 2023 17:31:18 +0200 Subject: [PATCH] convert more 'no-op if Creating' into check_at_caller+asserts --- pageserver/src/tenant.rs | 13 +++++++++---- pageserver/src/tenant/timeline.rs | 17 +++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index f318090712..71dc061485 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -1757,6 +1757,11 @@ impl Tenant { // execute on each timeline on the JoinSet, join after. let per_timeline = |timeline: Arc| { async move { + if let TimelineState::Creating = timeline.current_state() { + debug!("timeline is Creating, no need to flush it"); + // TODO cancel creation? Or is that done by higher level shutdown code? + return; + } match timeline.freeze_and_flush().await { Ok(()) => {} Err(err) => { @@ -2284,10 +2289,10 @@ impl Tenant { } let timelines_accessor = self.timelines.lock().unwrap(); - let not_broken_timelines = timelines_accessor - .values() - .filter(|timeline| !timeline.is_broken()); - for timeline in not_broken_timelines { + let timelines_to_stop = timelines_accessor.values().filter(|timeline| { + !timeline.is_broken() && !matches!(timeline.current_state(), TimelineState::Creating) + }); + for timeline in timelines_to_stop { timeline.set_state(TimelineState::Stopping); } Ok(()) diff --git a/pageserver/src/tenant/timeline.rs b/pageserver/src/tenant/timeline.rs index ca8942b577..1b7141cd58 100644 --- a/pageserver/src/tenant/timeline.rs +++ b/pageserver/src/tenant/timeline.rs @@ -691,12 +691,9 @@ impl Timeline { #[instrument(skip(self), fields(tenant_id=%self.tenant_id, timeline_id=%self.timeline_id))] pub async fn freeze_and_flush(&self) -> anyhow::Result<()> { if self.current_state() == TimelineState::Creating { - debug!("timelines in Creating state are never written to"); - assert!( - self.layers.read().await.open_layer.is_none(), - "would have nothing to flush anyways" - ); - return Ok(()); + // make a few additional sanity checks before panicking + assert!(self.layers.read().await.open_layer.is_none()); + panic!("caller must prevent calls for timelines in Creating state") } self.freeze_inmem_layer(false).await; self.flush_frozen_layers_and_wait().await @@ -704,10 +701,10 @@ impl Timeline { /// Outermost timeline compaction operation; downloads needed layers. pub async fn compact(self: &Arc, ctx: &RequestContext) -> anyhow::Result<()> { - if self.current_state() == TimelineState::Creating { - debug!("timelines is in Creating state"); - return Ok(()); - } + assert!( + !matches!(self.current_state(), TimelineState::Creating), + "caller must prevent calls for timelines in Creating state" + ); const ROUNDS: usize = 2;