[pbs-devel] [RFC proxmox-backup 15/36] client: restore: read payload from dedicated index

Christian Ebner c.ebner at proxmox.com
Wed Feb 28 15:02:05 CET 2024


Whenever a split pxar archive is encountered, instantiate and attach
the required dedicated reader instance to the decoder instance on
restore.

Piping the output to stdout is not possible, this would require a
decoder instance which can decode the input stream, while maintaining
the pxar stream format as output.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
 proxmox-backup-client/src/main.rs | 34 ++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index f252f5b7..c8ba67b4 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -1214,7 +1214,7 @@ async fn dump_image<W: Write>(
 fn parse_archive_type(name: &str) -> (String, ArchiveType) {
     if name.ends_with(".didx") || name.ends_with(".fidx") || name.ends_with(".blob") {
         (name.into(), archive_type(name).unwrap())
-    } else if name.ends_with(".pxar") {
+    } else if name.ends_with(".pxar") || name.ends_with(".pxar.meta") {
         (format!("{}.didx", name), ArchiveType::DynamicIndex)
     } else if name.ends_with(".img") {
         (format!("{}.fidx", name), ArchiveType::FixedIndex)
@@ -1456,7 +1456,7 @@ async fn restore(
 
         let chunk_reader = RemoteChunkReader::new(
             client.clone(),
-            crypt_config,
+            crypt_config.clone(),
             file_info.chunk_crypt_mode(),
             most_used,
         );
@@ -1516,8 +1516,33 @@ async fn restore(
         }
 
         if let Some(target) = target {
+            let mut decoder = pxar::decoder::Decoder::from_std(reader)?;
+            if let Some(archive_base_name) = archive_name.strip_suffix(".pxar.meta.didx") {
+                let payload_archive_name = format!("{archive_base_name}.pxar.pld.didx");
+
+                let payload_index = client
+                    .download_dynamic_index(&manifest, &payload_archive_name)
+                    .await?;
+
+                let payload_most_used = payload_index.find_most_used_chunks(8);
+
+                let payload_chunk_reader = RemoteChunkReader::new(
+                    client.clone(),
+                    crypt_config,
+                    file_info.chunk_crypt_mode(),
+                    payload_most_used,
+                );
+
+                let payload_reader =
+                    BufferedDynamicReader::new(payload_index, payload_chunk_reader);
+
+                decoder = decoder.redirect_payload_input(pxar::decoder::sync::StandardReader::new(
+                    payload_reader,
+                ));
+            }
+
             pbs_client::pxar::extract_archive(
-                pxar::decoder::Decoder::from_std(reader)?,
+                decoder,
                 Path::new(target),
                 feature_flags,
                 |path| {
@@ -1527,6 +1552,9 @@ async fn restore(
             )
             .map_err(|err| format_err!("error extracting archive - {:#}", err))?;
         } else {
+            if archive_name.ends_with(".pxar.meta.didx") {
+                bail!("unable to pipe pxar meta archive");
+            }
             let mut writer = std::fs::OpenOptions::new()
                 .write(true)
                 .open("/dev/stdout")
-- 
2.39.2





More information about the pbs-devel mailing list