From 2043221fca6e19b6d8f8ce2ff77949d2402bc4a4 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Mon, 27 Nov 2023 15:00:51 +0000 Subject: [PATCH] Squashed commit of the following: commit de90ba56d46e8e2e9e7a38a3db77af0042807726 Author: Christian Schwarz Date: Mon Nov 27 14:47:26 2023 +0000 expose generation number in API commit ae2c7589f98a7c72ad162f56da2bfd4e25c64267 Author: Christian Schwarz Date: Mon Nov 27 14:53:13 2023 +0000 pagectl: add subcommand to rewrite layer file history --- libs/pageserver_api/src/models.rs | 4 ++++ pageserver/src/consumption_metrics.rs | 2 +- pageserver/src/consumption_metrics/metrics.rs | 2 +- pageserver/src/disk_usage_eviction_task.rs | 2 +- pageserver/src/http/routes.rs | 4 +++- pageserver/src/tenant.rs | 4 ++++ pageserver/src/tenant/mgr.rs | 8 +++++--- 7 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libs/pageserver_api/src/models.rs b/libs/pageserver_api/src/models.rs index dea925b468..a93c47f5a2 100644 --- a/libs/pageserver_api/src/models.rs +++ b/libs/pageserver_api/src/models.rs @@ -368,6 +368,8 @@ pub struct TenantInfo { /// If a layer is present in both local FS and S3, it counts only once. pub current_physical_size: Option, // physical size is only included in `tenant_status` endpoint pub attachment_status: TenantAttachmentStatus, + #[serde(skip_serializing_if = "Option::is_none")] + pub generation: Option, } #[derive(Serialize, Deserialize, Clone)] @@ -909,6 +911,7 @@ mod tests { state: TenantState::Active, current_physical_size: Some(42), attachment_status: TenantAttachmentStatus::Attached, + generation: None, }; let expected_active = json!({ "id": original_active.id.to_string(), @@ -929,6 +932,7 @@ mod tests { }, current_physical_size: Some(42), attachment_status: TenantAttachmentStatus::Attached, + generation: None, }; let expected_broken = json!({ "id": original_broken.id.to_string(), diff --git a/pageserver/src/consumption_metrics.rs b/pageserver/src/consumption_metrics.rs index bde2cedca7..012a950b60 100644 --- a/pageserver/src/consumption_metrics.rs +++ b/pageserver/src/consumption_metrics.rs @@ -267,7 +267,7 @@ async fn calculate_synthetic_size_worker( } }; - for (tenant_shard_id, tenant_state) in tenants { + for (tenant_shard_id, tenant_state, _gen) in tenants { if tenant_state != TenantState::Active { continue; } diff --git a/pageserver/src/consumption_metrics/metrics.rs b/pageserver/src/consumption_metrics/metrics.rs index 0b827816bc..26b299a71d 100644 --- a/pageserver/src/consumption_metrics/metrics.rs +++ b/pageserver/src/consumption_metrics/metrics.rs @@ -196,7 +196,7 @@ pub(super) async fn collect_all_metrics( } }; - let tenants = futures::stream::iter(tenants).filter_map(|(id, state)| async move { + let tenants = futures::stream::iter(tenants).filter_map(|(id, state, _)| async move { if state != TenantState::Active || !id.is_zero() { None } else { diff --git a/pageserver/src/disk_usage_eviction_task.rs b/pageserver/src/disk_usage_eviction_task.rs index 23b9b573b6..7d74da1196 100644 --- a/pageserver/src/disk_usage_eviction_task.rs +++ b/pageserver/src/disk_usage_eviction_task.rs @@ -633,7 +633,7 @@ async fn collect_eviction_candidates( let mut candidates = Vec::new(); - for (tenant_id, _state) in &tenants { + for (tenant_id, _state, _gen) in &tenants { if cancel.is_cancelled() { return Ok(EvictionCandidates::Cancelled); } diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index 5c7747d353..f5347f23b4 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -830,11 +830,12 @@ async fn tenant_list_handler( ApiError::ResourceUnavailable("Tenant map is initializing or shutting down".into()) })? .iter() - .map(|(id, state)| TenantInfo { + .map(|(id, state, gen)| TenantInfo { id: *id, state: state.clone(), current_physical_size: None, attachment_status: state.attachment_status(), + generation: (*gen).into(), }) .collect::>(); @@ -864,6 +865,7 @@ async fn tenant_status( state: state.clone(), current_physical_size: Some(current_physical_size), attachment_status: state.attachment_status(), + generation: tenant.generation().into(), }, timelines: tenant.list_timeline_ids(), }) diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index 7c609452e5..4728bc12c6 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -1923,6 +1923,10 @@ impl Tenant { self.current_state() == TenantState::Active } + pub fn generation(&self) -> Generation { + self.generation + } + /// Changes tenant status to active, unless shutdown was already requested. /// /// `background_jobs_can_start` is an optional barrier set to a value during pageserver startup diff --git a/pageserver/src/tenant/mgr.rs b/pageserver/src/tenant/mgr.rs index 70b41b7b1f..79fd5e4476 100644 --- a/pageserver/src/tenant/mgr.rs +++ b/pageserver/src/tenant/mgr.rs @@ -1632,8 +1632,8 @@ pub(crate) enum TenantMapListError { /// /// Get list of tenants, for the mgmt API /// -pub(crate) async fn list_tenants() -> Result, TenantMapListError> -{ +pub(crate) async fn list_tenants( +) -> Result, TenantMapListError> { let tenants = TENANTS.read().unwrap(); let m = match &*tenants { TenantsMap::Initializing => return Err(TenantMapListError::Initializing), @@ -1641,7 +1641,9 @@ pub(crate) async fn list_tenants() -> Result, }; Ok(m.iter() .filter_map(|(id, tenant)| match tenant { - TenantSlot::Attached(tenant) => Some((*id, tenant.current_state())), + TenantSlot::Attached(tenant) => { + Some((*id, tenant.current_state(), tenant.generation())) + } TenantSlot::Secondary(_) => None, TenantSlot::InProgress(_) => None, })