mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-16 01:42:55 +00:00
fixes https://github.com/neondatabase/neon/issues/5878 obsoletes https://github.com/neondatabase/neon/issues/5879 Before this PR, it could happen that `load_layer_map` schedules removal of the future image layer. Then a later compaction run could re-create the same image layer, scheduling a PUT. Due to lack of an upload queue barrier, the PUT and DELETE could be re-ordered. The result was IndexPart referencing a non-existent object. ## Summary of changes * Add support to `pagectl` / Python tests to decode `IndexPart` * Rust * new `pagectl` Subcommand * `IndexPart::{from,to}_s3_bytes()` methods to internalize knowledge about encoding of `IndexPart` * Python * new `NeonCli` subclass * Add regression test * Rust * Ability to force repartitioning; required to ensure image layer creation at last_record_lsn * Python * The regression test. * Fix the issue * Insert an `UploadOp::Barrier` after scheduling the deletions.
39 lines
1.3 KiB
Rust
39 lines
1.3 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use anyhow::Context;
|
|
use camino::Utf8PathBuf;
|
|
use pageserver::tenant::remote_timeline_client::index::IndexLayerMetadata;
|
|
use pageserver::tenant::storage_layer::LayerFileName;
|
|
use pageserver::tenant::{metadata::TimelineMetadata, IndexPart};
|
|
use utils::lsn::Lsn;
|
|
|
|
#[derive(clap::Subcommand)]
|
|
pub(crate) enum IndexPartCmd {
|
|
Dump { path: Utf8PathBuf },
|
|
}
|
|
|
|
pub(crate) async fn main(cmd: &IndexPartCmd) -> anyhow::Result<()> {
|
|
match cmd {
|
|
IndexPartCmd::Dump { path } => {
|
|
let bytes = tokio::fs::read(path).await.context("read file")?;
|
|
let des: IndexPart = IndexPart::from_s3_bytes(&bytes).context("deserialize")?;
|
|
#[derive(serde::Serialize)]
|
|
struct Output<'a> {
|
|
layer_metadata: &'a HashMap<LayerFileName, IndexLayerMetadata>,
|
|
disk_consistent_lsn: Lsn,
|
|
timeline_metadata: &'a TimelineMetadata,
|
|
}
|
|
|
|
let output = Output {
|
|
layer_metadata: &des.layer_metadata,
|
|
disk_consistent_lsn: des.get_disk_consistent_lsn(),
|
|
timeline_metadata: &des.metadata,
|
|
};
|
|
|
|
let output = serde_json::to_string_pretty(&output).context("serialize output")?;
|
|
println!("{output}");
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|