Add TenantState::NotLoaded

This commit is contained in:
Konstantin Knizhnik
2023-06-02 22:06:39 +03:00
parent 36eb1c83f3
commit 3e044a1405
3 changed files with 29 additions and 9 deletions

View File

@@ -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"),
(

View File

@@ -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| {

View File

@@ -617,7 +617,14 @@ pub async fn list_tenants() -> Result<Vec<(TenantId, TenantState)>, 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) => {