Print in-memory layers info

This commit is contained in:
Kirill Bulatov
2023-01-25 16:30:55 +02:00
parent 5ee77c0b1f
commit f3096d85e0
5 changed files with 101 additions and 5 deletions

View File

@@ -1,4 +1,7 @@
use std::num::{NonZeroU64, NonZeroUsize};
use std::{
collections::BTreeSet,
num::{NonZeroU64, NonZeroUsize},
};
use byteorder::{BigEndian, ReadBytesExt};
use serde::{Deserialize, Serialize};
@@ -227,6 +230,39 @@ pub struct TimelineInfo {
pub state: TimelineState,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize)]
pub struct LayerMapInfo {
pub in_memory_layers: BTreeSet<InMemoryLayerInfo>,
pub historic_layers: BTreeSet<HistoricLayerInfo>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum InMemoryLayerInfo {
Open { lsn_start: Lsn },
Frozen { lsn_start: Lsn, lsn_end: Lsn },
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum HistoricLayerInfo {
Delta {
layer_file_name: String,
key_start: String,
key_end: String,
lsn_start: Lsn,
lsn_end: Lsn,
remote: bool,
},
Image {
layer_file_name: String,
key_start: String,
key_end: String,
lsn_start: Lsn,
remote: bool,
},
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DownloadRemoteLayersTaskSpawnRequest {
pub max_concurrent_downloads: NonZeroUsize,

View File

@@ -556,6 +556,25 @@ async fn tenant_size_handler(request: Request<Body>) -> Result<Response<Body>, A
)
}
async fn timeline_layer_map_info_handler(
request: Request<Body>,
) -> Result<Response<Body>, ApiError> {
let tenant_id: TenantId = parse_request_param(&request, "tenant_id")?;
let timeline_id: TimelineId = parse_request_param(&request, "timeline_id")?;
check_permission(&request, Some(tenant_id))?;
let tenant = mgr::get_tenant(tenant_id, true)
.await
.map_err(ApiError::NotFound)?;
let timeline = tenant
.get_timeline(timeline_id, true)
.map_err(ApiError::NotFound)?;
let layer_map_info = timeline.layer_map_info();
json_response(StatusCode::OK, layer_map_info)
}
// Helper function to standardize the error messages we produce on bad durations
//
// Intended to be used with anyhow's `with_context`, e.g.:
@@ -986,5 +1005,9 @@ pub fn make_router(
"/v1/tenant/:tenant_id/timeline/:timeline_id",
timeline_delete_handler,
)
.get(
"/v1/tenant/:tenant_id/timeline/:timeline_id/layer",
timeline_layer_map_info_handler,
)
.any(handler_404))
}

View File

@@ -52,12 +52,13 @@ use crate::repository::Key;
use crate::tenant::storage_layer::InMemoryLayer;
use crate::tenant::storage_layer::Layer;
use anyhow::Result;
use std::collections::VecDeque;
use std::collections::{BTreeSet, VecDeque};
use std::ops::Range;
use std::sync::Arc;
use utils::lsn::Lsn;
use historic_layer_coverage::BufferedHistoricLayerCoverage;
use pageserver_api::models::LayerMapInfo;
use super::storage_layer::range_eq;
@@ -674,4 +675,26 @@ where
println!("End dump LayerMap");
Ok(())
}
// TODO kb comments + swagger schema
pub fn info(&self) -> LayerMapInfo {
let mut in_memory_layers = BTreeSet::new();
if let Some(open_layer) = &self.open_layer {
in_memory_layers.insert(open_layer.info());
}
for frozen_layer in &self.frozen_layers {
in_memory_layers.insert(frozen_layer.info());
}
let mut historic_layers = BTreeSet::new();
for historic_layer in self.iter_historic_layers() {
// TODO kb what to use here for `historic_layer: Arc<L>` ?
// historic_layers.insert(historic_layer.info());
}
LayerMapInfo {
in_memory_layers,
historic_layers,
}
}
}

View File

@@ -12,6 +12,7 @@ use crate::tenant::ephemeral_file::EphemeralFile;
use crate::tenant::storage_layer::{ValueReconstructResult, ValueReconstructState};
use crate::walrecord;
use anyhow::{ensure, Result};
use pageserver_api::models::InMemoryLayerInfo;
use std::cell::RefCell;
use std::collections::HashMap;
use tracing::*;
@@ -79,6 +80,16 @@ impl InMemoryLayer {
pub fn get_timeline_id(&self) -> TimelineId {
self.timeline_id
}
pub fn info(&self) -> InMemoryLayerInfo {
let lsn_start = self.start_lsn;
let lsn_end = self.inner.read().unwrap().end_lsn;
match lsn_end {
Some(lsn_end) => InMemoryLayerInfo::Frozen { lsn_start, lsn_end },
None => InMemoryLayerInfo::Open { lsn_start },
}
}
}
impl Layer for InMemoryLayer {
@@ -108,7 +119,6 @@ impl Layer for InMemoryLayer {
let end_lsn = inner.end_lsn.unwrap_or(Lsn(u64::MAX));
format!("inmem-{:016X}-{:016X}", self.start_lsn.0, end_lsn.0)
}
/// debugging function to print out the contents of the layer
fn dump(&self, verbose: bool) -> Result<()> {
let inner = self.inner.read().unwrap();

View File

@@ -10,7 +10,7 @@ use itertools::Itertools;
use once_cell::sync::OnceCell;
use pageserver_api::models::{
DownloadRemoteLayersTaskInfo, DownloadRemoteLayersTaskSpawnRequest,
DownloadRemoteLayersTaskState, TimelineState,
DownloadRemoteLayersTaskState, LayerMapInfo, TimelineState,
};
use tokio::sync::{oneshot, watch, Semaphore, TryAcquireError};
use tokio_util::sync::CancellationToken;
@@ -90,7 +90,7 @@ pub struct Timeline {
pub pg_version: u32,
pub layers: RwLock<LayerMap<dyn PersistentLayer>>,
pub(super) layers: RwLock<LayerMap<dyn PersistentLayer>>,
last_freeze_at: AtomicLsn,
// Atomic would be more appropriate here.
@@ -818,6 +818,10 @@ impl Timeline {
pub fn subscribe_for_state_updates(&self) -> watch::Receiver<TimelineState> {
self.state.subscribe()
}
pub fn layer_map_info(&self) -> LayerMapInfo {
self.layers.read().unwrap().info()
}
}
// Private functions