From 3e044a14050695a12156baf8eadfb0504780aa20 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Fri, 2 Jun 2023 22:06:39 +0300 Subject: [PATCH] Add TenantState::NotLoaded --- libs/pageserver_api/src/models.rs | 6 +++++- pageserver/src/tenant.rs | 21 +++++++++++++++------ pageserver/src/tenant/mgr.rs | 11 +++++++++-- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/libs/pageserver_api/src/models.rs b/libs/pageserver_api/src/models.rs index 162bf6b294..6c4821d689 100644 --- a/libs/pageserver_api/src/models.rs +++ b/libs/pageserver_api/src/models.rs @@ -54,6 +54,9 @@ use bytes::{BufMut, Bytes, BytesMut}; )] #[serde(tag = "slug", content = "data")] pub enum TenantState { + /// This tenant is not yet loaded + /// + NotLoaded, /// This tenant is being loaded from local disk. /// /// `set_stopping()` and `set_broken()` do not work in this state and wait for it to pass. @@ -104,7 +107,7 @@ impl TenantState { Self::Attaching | Self::Activating(ActivatingFrom::Attaching) => Maybe, // tenant mgr startup distinguishes attaching from loading via marker file. // If it's loading, there is no attach marker file, i.e., attach had finished in the past. - Self::Loading | Self::Activating(ActivatingFrom::Loading) => Attached, + Self::NotLoaded | Self::Loading | Self::Activating(ActivatingFrom::Loading) => Attached, // We only reach Active after successful load / attach. // So, call atttachment status Attached. Self::Active => Attached, @@ -907,6 +910,7 @@ mod tests { fn tenantstatus_activating_strum() { // tests added, because we use these for metrics let examples = [ + (line!(), TenantState::NotLoaded, "Not Loaded"), (line!(), TenantState::Loading, "Loading"), (line!(), TenantState::Attaching, "Attaching"), ( diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs index af6a70c4f2..a370ba118c 100644 --- a/pageserver/src/tenant.rs +++ b/pageserver/src/tenant.rs @@ -1694,7 +1694,7 @@ impl Tenant { self.state.send_modify(|current_state| { use pageserver_api::models::ActivatingFrom; match &*current_state { - TenantState::Activating(_) | TenantState::Active | TenantState::Broken { .. } | TenantState::Stopping => { + TenantState::NotLoaded | TenantState::Activating(_) | TenantState::Active | TenantState::Broken { .. } | TenantState::Stopping => { panic!("caller is responsible for calling activate() only on Loading / Attaching tenants, got {state:?}", state = current_state); } TenantState::Loading => { @@ -1761,7 +1761,10 @@ impl Tenant { // cannot stop before we're done activating, so wait out until we're done activating rx.wait_for(|state| match state { - TenantState::Activating(_) | TenantState::Loading | TenantState::Attaching => { + TenantState::NotLoaded + | TenantState::Activating(_) + | TenantState::Loading + | TenantState::Attaching => { info!( "waiting for {} to turn Active|Broken|Stopping", <&'static str>::from(state) @@ -1776,7 +1779,7 @@ impl Tenant { // we now know we're done activating, let's see whether this task is the winner to transition into Stopping let mut err = None; let stopping = self.state.send_if_modified(|current_state| match current_state { - TenantState::Activating(_) | TenantState::Loading | TenantState::Attaching => { + TenantState::NotLoaded | TenantState::Activating(_) | TenantState::Loading | TenantState::Attaching => { unreachable!("we ensured above that we're done with activation, and, there is no re-activation") } TenantState::Active => { @@ -1834,7 +1837,10 @@ impl Tenant { // The load & attach routines own the tenant state until it has reached `Active`. // So, wait until it's done. rx.wait_for(|state| match state { - TenantState::Activating(_) | TenantState::Loading | TenantState::Attaching => { + TenantState::NotLoaded + | TenantState::Activating(_) + | TenantState::Loading + | TenantState::Attaching => { info!( "waiting for {} to turn Active|Broken|Stopping", <&'static str>::from(state) @@ -1849,7 +1855,7 @@ impl Tenant { // we now know we're done activating, let's see whether this task is the winner to transition into Broken self.state.send_modify(|current_state| { match *current_state { - TenantState::Activating(_) | TenantState::Loading | TenantState::Attaching => { + TenantState::NotLoaded | TenantState::Activating(_) | TenantState::Loading | TenantState::Attaching => { unreachable!("we ensured above that we're done with activation, and, there is no re-activation") } TenantState::Active => { @@ -1884,7 +1890,10 @@ impl Tenant { loop { let current_state = receiver.borrow_and_update().clone(); match current_state { - TenantState::Loading | TenantState::Attaching | TenantState::Activating(_) => { + TenantState::NotLoaded + | TenantState::Loading + | TenantState::Attaching + | TenantState::Activating(_) => { // in these states, there's a chance that we can reach ::Active receiver.changed().await.map_err( |_e: tokio::sync::watch::error::RecvError| { diff --git a/pageserver/src/tenant/mgr.rs b/pageserver/src/tenant/mgr.rs index fa0a26ae1a..009d260260 100644 --- a/pageserver/src/tenant/mgr.rs +++ b/pageserver/src/tenant/mgr.rs @@ -617,7 +617,14 @@ pub async fn list_tenants() -> Result, TenantMapLis TenantsMap::Open(m) => Ok(m .map .iter() - .filter_map(|(k, v)| v.get().map(|tenant| (*k, tenant.current_state()))) + .map(|(id, tenant)| { + ( + *id, + tenant + .get() + .map_or(TenantState::NotLoaded, |tenant| tenant.current_state()), + ) + }) .collect()), TenantsMap::ShuttingDown(m) => Ok(m .iter() @@ -699,7 +706,7 @@ where tenant_id, e.get() .get() - .map_or(TenantState::Loading, |tenant| tenant.current_state()), + .map_or(TenantState::NotLoaded, |tenant| tenant.current_state()), )), hash_map::Entry::Vacant(v) => match insert_fn() { Ok(tenant) => {