Skip to content

Commit

Permalink
add Tenant::store_tenant_manifest
Browse files Browse the repository at this point in the history
  • Loading branch information
jcsp committed Oct 29, 2024
1 parent 25f1e5c commit fcf2a6d
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions pageserver/src/tenant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ pub struct Tenant {
/// **Lock order**: if acquiring all (or a subset), acquire them in order `timelines`, `timelines_offloaded`, `timelines_creating`
timelines_offloaded: Mutex<HashMap<TimelineId, Arc<OffloadedTimeline>>>,

/// Serialize writes of the tenant manifest to remote storage
tenant_manifest_upload: tokio::sync::Mutex<()>,

// This mutex prevents creation of new timelines during GC.
// Adding yet another mutex (in addition to `timelines`) is needed because holding
// `timelines` mutex during all GC iteration
Expand Down Expand Up @@ -749,6 +752,15 @@ pub enum TimelineArchivalError {
Other(anyhow::Error),
}

#[derive(thiserror::Error, Debug)]
pub(crate) enum TenantManifestError {
#[error("Remote storage error: {0}")]
RemoteStorage(anyhow::Error),

#[error("Cancelled")]
Cancelled,
}

impl Debug for TimelineArchivalError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expand Down Expand Up @@ -3525,6 +3537,7 @@ impl Tenant {
timelines: Mutex::new(HashMap::new()),
timelines_creating: Mutex::new(HashSet::new()),
timelines_offloaded: Mutex::new(HashMap::new()),
tenant_manifest_upload: Default::default(),
gc_cs: tokio::sync::Mutex::new(()),
walredo_mgr,
remote_storage,
Expand Down Expand Up @@ -4704,6 +4717,38 @@ impl Tenant {
.max()
.unwrap_or(0)
}

/// Serialize and write the latest TenantManifest to remote storage.
pub(crate) async fn store_tenant_manifest(&self) -> Result<(), TenantManifestError> {
// Only one manifest write may be done at at time, and the contents of the manifest
// must be loaded while holding this lock. This makes it safe to call this function
// from anywhere without worrying about colliding updates.
let _guard = tokio::select! {
g = self.tenant_manifest_upload.lock() => {
g
},
_ = self.cancel.cancelled() => {
return Err(TenantManifestError::Cancelled);
}
};

let manifest = self.tenant_manifest();
upload_tenant_manifest(
&self.remote_storage,
&self.tenant_shard_id,
self.generation,
&manifest,
&self.cancel,
)
.await
.map_err(|e| {
if self.cancel.is_cancelled() {
TenantManifestError::Cancelled
} else {
TenantManifestError::RemoteStorage(e)
}
})
}
}

/// Create the cluster temporarily in 'initdbpath' directory inside the repository
Expand Down

0 comments on commit fcf2a6d

Please sign in to comment.