From 00f7fc324d44dfd16001cfa1b0b01a1c534ef0e0 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Tue, 23 May 2023 21:16:12 +0200 Subject: [PATCH] tenant_map_insert: don't expose the vacant entry to the closure (#4316) This tightens up the API a little. Byproduct of some refactoring work that I'm doing right now. --- pageserver/src/tenant/mgr.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/pageserver/src/tenant/mgr.rs b/pageserver/src/tenant/mgr.rs index 1542d34a6632..53d69a15dcdf 100644 --- a/pageserver/src/tenant/mgr.rs +++ b/pageserver/src/tenant/mgr.rs @@ -278,7 +278,7 @@ pub async fn create_tenant( remote_storage: Option, ctx: &RequestContext, ) -> Result, TenantMapInsertError> { - tenant_map_insert(tenant_id, |vacant_entry| { + tenant_map_insert(tenant_id, || { // We're holding the tenants lock in write mode while doing local IO. // If this section ever becomes contentious, introduce a new `TenantState::Creating` // and do the work in that state. @@ -296,7 +296,6 @@ pub async fn create_tenant( tenant_id == crated_tenant_id, "loaded created tenant has unexpected tenant id (expect {tenant_id} != actual {crated_tenant_id})", ); - vacant_entry.insert(Arc::clone(&created_tenant)); Ok(created_tenant) }).await } @@ -408,7 +407,7 @@ pub async fn load_tenant( remote_storage: Option, ctx: &RequestContext, ) -> Result<(), TenantMapInsertError> { - tenant_map_insert(tenant_id, |vacant_entry| { + tenant_map_insert(tenant_id, || { let tenant_path = conf.tenant_path(&tenant_id); let tenant_ignore_mark = conf.tenant_ignore_mark_file_path(tenant_id); if tenant_ignore_mark.exists() { @@ -421,9 +420,9 @@ pub async fn load_tenant( format!("Failed to schedule tenant processing in path {tenant_path:?}") })?; - vacant_entry.insert(new_tenant); - Ok(()) - }).await + Ok(new_tenant) + }).await?; + Ok(()) } pub async fn ignore_tenant( @@ -476,7 +475,7 @@ pub async fn attach_tenant( remote_storage: GenericRemoteStorage, ctx: &RequestContext, ) -> Result<(), TenantMapInsertError> { - tenant_map_insert(tenant_id, |vacant_entry| { + tenant_map_insert(tenant_id, || { let tenant_dir = create_tenant_files(conf, tenant_conf, tenant_id, CreateTenantFilesMode::Attach)?; // TODO: tenant directory remains on disk if we bail out from here on. // See https://github.com/neondatabase/neon/issues/4233 @@ -497,10 +496,10 @@ pub async fn attach_tenant( tenant_id == attached_tenant_id, "loaded created tenant has unexpected tenant id (expect {tenant_id} != actual {attached_tenant_id})", ); - vacant_entry.insert(Arc::clone(&attached_tenant)); - Ok(()) + Ok(attached_tenant) }) - .await + .await?; + Ok(()) } #[derive(Debug, thiserror::Error)] @@ -521,12 +520,12 @@ pub enum TenantMapInsertError { /// /// NB: the closure should return quickly because the current implementation of tenants map /// serializes access through an `RwLock`. -async fn tenant_map_insert( +async fn tenant_map_insert( tenant_id: TenantId, insert_fn: F, -) -> Result +) -> Result, TenantMapInsertError> where - F: FnOnce(hash_map::VacantEntry>) -> anyhow::Result, + F: FnOnce() -> anyhow::Result>, { let mut guard = TENANTS.write().await; let m = match &mut *guard { @@ -539,8 +538,11 @@ where tenant_id, e.get().current_state(), )), - hash_map::Entry::Vacant(v) => match insert_fn(v) { - Ok(v) => Ok(v), + hash_map::Entry::Vacant(v) => match insert_fn() { + Ok(tenant) => { + v.insert(tenant.clone()); + Ok(tenant) + } Err(e) => Err(TenantMapInsertError::Closure(e)), }, }