From 55aeeb5765a12ad318fe3c72f5c14aeab075b959 Mon Sep 17 00:00:00 2001 From: Joonas Koivunen Date: Fri, 19 Jul 2024 16:08:03 +0000 Subject: [PATCH] allow deleting timeline unblock gc --- pageserver/src/tenant/timeline/delete.rs | 2 ++ .../src/tenant/timeline/detach_ancestor.rs | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/pageserver/src/tenant/timeline/delete.rs b/pageserver/src/tenant/timeline/delete.rs index ab6a5f20ba..d69022143f 100644 --- a/pageserver/src/tenant/timeline/delete.rs +++ b/pageserver/src/tenant/timeline/delete.rs @@ -221,6 +221,8 @@ impl DeleteTimelineFlow { // Now that the Timeline is in Stopping state, request all the related tasks to shut down. timeline.shutdown(super::ShutdownMode::Hard).await; + tenant.ongoing_timeline_detach.on_delete(&timeline); + fail::fail_point!("timeline-delete-before-index-deleted-at", |_| { Err(anyhow::anyhow!( "failpoint: timeline-delete-before-index-deleted-at" diff --git a/pageserver/src/tenant/timeline/detach_ancestor.rs b/pageserver/src/tenant/timeline/detach_ancestor.rs index d7da944d31..284979b31b 100644 --- a/pageserver/src/tenant/timeline/detach_ancestor.rs +++ b/pageserver/src/tenant/timeline/detach_ancestor.rs @@ -446,6 +446,42 @@ impl SharedStateInner { assert!(!self.known_ongoing.is_empty()); self.latest = Some((ExistingAttempt::ReadFromIndexPart, witnessed)); } + + fn on_delete(&mut self, timeline_id: &TimelineId) { + let witnessed = match self.latest.as_ref() { + Some((ExistingAttempt::Actual(x, barrier), witnessed)) if x == timeline_id => { + assert!( + barrier.is_ready(), + "the attempt is still ongoing; is this call happening before closing the gate?" + ); + *witnessed + } + Some((ExistingAttempt::ContinuedOverRestart(x), witnessed)) if x == timeline_id => { + *witnessed + } + Some((ExistingAttempt::ReadFromIndexPart, witnessed)) + if self.known_ongoing.contains(timeline_id) => + { + *witnessed + } + _ => return, + }; + + assert!(self.known_ongoing.remove(timeline_id)); + + if self.known_ongoing.is_empty() { + self.latest = None; + tracing::info!("gc is now unblocked following timeline deletion"); + } else { + self.latest = Some((ExistingAttempt::ReadFromIndexPart, witnessed)); + tracing::info!( + n = self.known_ongoing.len(), + "gc is still blocked for remaining ongoing detaches" + ); + } + + todo!("there should be a test for this.") + } } #[derive(Debug)]