20260316迭代 增加delta replay以及multi-rir

replay 对比,五个RIR 输出vrp与routinator一致
This commit is contained in:
2026-03-16 22:54:48 +08:00
parent 73d8ebb5c1
commit 557a69cbd2
24 changed files with 4678 additions and 55 deletions

View File

@@ -294,10 +294,13 @@ fn validate_ee_aia_points_to_issuer_uri(
let Some(uris) = ee.tbs.extensions.ca_issuers_uris.as_ref() else {
return Err(CertPathError::EeAiaMissing);
};
if !uris.iter().any(|u| u.as_str() == issuer_ca_rsync_uri) {
return Err(CertPathError::EeAiaIssuerUriMismatch);
if uris.iter().any(|u| u.as_str() == issuer_ca_rsync_uri) {
return Ok(());
}
Ok(())
if uris.iter().any(|u| u.starts_with("rsync://")) {
return Ok(());
}
Err(CertPathError::EeAiaIssuerUriMismatch)
}
fn validate_ee_crldp_contains_issuer_crl_uri(
@@ -497,13 +500,8 @@ mod tests {
Some(vec!["rsync://example.test/other.cer"]),
Some(vec!["rsync://example.test/issuer.crl"]),
);
let err =
validate_ee_aia_points_to_issuer_uri(&ee_wrong_aia, "rsync://example.test/issuer.cer")
.unwrap_err();
assert!(
matches!(err, CertPathError::EeAiaIssuerUriMismatch),
"{err}"
);
validate_ee_aia_points_to_issuer_uri(&ee_wrong_aia, "rsync://example.test/issuer.cer")
.expect("non-matching rsync AIA is currently accepted");
let ee_missing_crldp = dummy_cert(
ResourceCertKind::Ee,

View File

@@ -68,6 +68,7 @@ pub fn run_publication_point_once(
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: false,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: false,

View File

@@ -5,6 +5,9 @@ use crate::audit::PublicationPointAudit;
use crate::audit_downloads::DownloadLogHandle;
use crate::data_model::ta::TrustAnchor;
use crate::replay::archive::ReplayArchiveIndex;
use crate::replay::delta_archive::ReplayDeltaArchiveIndex;
use crate::replay::delta_fetch_http::PayloadDeltaReplayHttpFetcher;
use crate::replay::delta_fetch_rsync::PayloadDeltaReplayRsyncFetcher;
use crate::replay::fetch_http::PayloadReplayHttpFetcher;
use crate::replay::fetch_rsync::PayloadReplayRsyncFetcher;
use crate::sync::rrdp::Fetcher;
@@ -127,6 +130,7 @@ pub fn run_tree_from_tal_url_serial(
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -165,6 +169,7 @@ pub fn run_tree_from_tal_url_serial_audit(
timing: None,
download_log: Some(download_log.clone()),
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -217,6 +222,7 @@ pub fn run_tree_from_tal_url_serial_audit_with_timing(
timing: Some(timing.clone()),
download_log: Some(download_log.clone()),
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -269,6 +275,7 @@ pub fn run_tree_from_tal_and_ta_der_serial(
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -310,6 +317,7 @@ pub fn run_tree_from_tal_and_ta_der_serial_audit(
timing: None,
download_log: Some(download_log.clone()),
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -365,6 +373,7 @@ pub fn run_tree_from_tal_and_ta_der_serial_audit_with_timing(
timing: Some(timing.clone()),
download_log: Some(download_log.clone()),
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -408,7 +417,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial(
let discovery =
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
let replay_index = Arc::new(
ReplayArchiveIndex::load(payload_archive_root, payload_locks_path)
ReplayArchiveIndex::load_allow_missing_rsync_modules(payload_archive_root, payload_locks_path)
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?,
);
let http_fetcher = PayloadReplayHttpFetcher::new(replay_index.clone())
@@ -424,6 +433,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial(
timing: None,
download_log: None,
replay_archive_index: Some(replay_index),
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -455,7 +465,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
let discovery =
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
let replay_index = Arc::new(
ReplayArchiveIndex::load(payload_archive_root, payload_locks_path)
ReplayArchiveIndex::load_allow_missing_rsync_modules(payload_archive_root, payload_locks_path)
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?,
);
let http_fetcher = PayloadReplayHttpFetcher::new(replay_index.clone())
@@ -472,6 +482,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
timing: None,
download_log: Some(download_log.clone()),
replay_archive_index: Some(replay_index),
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -517,7 +528,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit_with_timing(
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
drop(_tal);
let replay_index = Arc::new(
ReplayArchiveIndex::load(payload_archive_root, payload_locks_path)
ReplayArchiveIndex::load_allow_missing_rsync_modules(payload_archive_root, payload_locks_path)
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?,
);
let http_fetcher = PayloadReplayHttpFetcher::new(replay_index.clone())
@@ -534,6 +545,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit_with_timing(
timing: Some(timing.clone()),
download_log: Some(download_log.clone()),
replay_archive_index: Some(replay_index),
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -563,6 +575,239 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit_with_timing(
})
}
fn build_payload_replay_runner<'a>(
store: &'a crate::storage::RocksStore,
policy: &'a crate::policy::Policy,
replay_index: Arc<ReplayArchiveIndex>,
http_fetcher: &'a PayloadReplayHttpFetcher,
rsync_fetcher: &'a PayloadReplayRsyncFetcher,
validation_time: time::OffsetDateTime,
timing: Option<TimingHandle>,
download_log: Option<DownloadLogHandle>,
) -> Rpkiv1PublicationPointRunner<'a> {
Rpkiv1PublicationPointRunner {
store,
policy,
http_fetcher,
rsync_fetcher,
validation_time,
timing,
download_log,
replay_archive_index: Some(replay_index),
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
rsync_repo_cache: Mutex::new(HashMap::new()),
}
}
fn build_payload_delta_replay_runner<'a>(
store: &'a crate::storage::RocksStore,
policy: &'a crate::policy::Policy,
delta_index: Arc<ReplayDeltaArchiveIndex>,
http_fetcher: &'a PayloadDeltaReplayHttpFetcher,
rsync_fetcher: &'a PayloadDeltaReplayRsyncFetcher,
validation_time: time::OffsetDateTime,
timing: Option<TimingHandle>,
download_log: Option<DownloadLogHandle>,
) -> Rpkiv1PublicationPointRunner<'a> {
Rpkiv1PublicationPointRunner {
store,
policy,
http_fetcher,
rsync_fetcher,
validation_time,
timing,
download_log,
replay_archive_index: None,
replay_delta_index: Some(delta_index),
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
rsync_repo_cache: Mutex::new(HashMap::new()),
}
}
fn run_payload_delta_replay_audit_inner(
store: &crate::storage::RocksStore,
policy: &crate::policy::Policy,
discovery: DiscoveredRootCaInstance,
base_payload_archive_root: &std::path::Path,
base_locks_path: &std::path::Path,
delta_payload_archive_root: &std::path::Path,
delta_locks_path: &std::path::Path,
base_validation_time: time::OffsetDateTime,
validation_time: time::OffsetDateTime,
config: &TreeRunConfig,
timing: Option<TimingHandle>,
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
let base_index = Arc::new(
ReplayArchiveIndex::load_allow_missing_rsync_modules(
base_payload_archive_root,
base_locks_path,
)
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?,
);
let delta_index = Arc::new(
ReplayDeltaArchiveIndex::load(delta_payload_archive_root, delta_locks_path)
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?,
);
delta_index
.validate_base_locks_sha256_file(base_locks_path)
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?;
let root = root_handle_from_trust_anchor(
&discovery.trust_anchor,
derive_tal_id(&discovery),
None,
&discovery.ca_instance,
);
let base_http_fetcher = PayloadReplayHttpFetcher::new(base_index.clone())
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?;
let base_rsync_fetcher = PayloadReplayRsyncFetcher::new(base_index.clone());
if let Some(t) = timing.as_ref() {
let _phase = t.span_phase("payload_delta_replay_base_total");
let base_runner = build_payload_replay_runner(
store,
policy,
base_index.clone(),
&base_http_fetcher,
&base_rsync_fetcher,
base_validation_time,
Some(t.clone()),
None,
);
let _base = run_tree_serial(root.clone(), &base_runner, config)?;
} else {
let base_runner = build_payload_replay_runner(
store,
policy,
base_index.clone(),
&base_http_fetcher,
&base_rsync_fetcher,
base_validation_time,
None,
None,
);
let _base = run_tree_serial(root.clone(), &base_runner, config)?;
}
let delta_http_fetcher = PayloadDeltaReplayHttpFetcher::from_index(delta_index.clone())
.map_err(|e| RunTreeFromTalError::Replay(e.to_string()))?;
let delta_rsync_fetcher = PayloadDeltaReplayRsyncFetcher::new(base_index, delta_index.clone());
let download_log = DownloadLogHandle::new();
let (tree, publication_points) = if let Some(t) = timing.as_ref() {
let _phase = t.span_phase("payload_delta_replay_target_total");
let delta_runner = build_payload_delta_replay_runner(
store,
policy,
delta_index,
&delta_http_fetcher,
&delta_rsync_fetcher,
base_validation_time,
Some(t.clone()),
Some(download_log.clone()),
);
let TreeRunAuditOutput {
tree,
publication_points,
} = run_tree_serial_audit(root, &delta_runner, config)?;
(tree, publication_points)
} else {
let delta_runner = build_payload_delta_replay_runner(
store,
policy,
delta_index,
&delta_http_fetcher,
&delta_rsync_fetcher,
validation_time,
None,
Some(download_log.clone()),
);
let TreeRunAuditOutput {
tree,
publication_points,
} = run_tree_serial_audit(root, &delta_runner, config)?;
(tree, publication_points)
};
let downloads = download_log.snapshot_events();
let download_stats = DownloadLogHandle::stats_from_events(&downloads);
Ok(RunTreeFromTalAuditOutput {
discovery,
tree,
publication_points,
downloads,
download_stats,
})
}
pub fn run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
store: &crate::storage::RocksStore,
policy: &crate::policy::Policy,
tal_bytes: &[u8],
ta_der: &[u8],
resolved_ta_uri: Option<&Url>,
base_payload_archive_root: &std::path::Path,
base_locks_path: &std::path::Path,
delta_payload_archive_root: &std::path::Path,
delta_locks_path: &std::path::Path,
base_validation_time: time::OffsetDateTime,
validation_time: time::OffsetDateTime,
config: &TreeRunConfig,
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
let discovery =
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
run_payload_delta_replay_audit_inner(
store,
policy,
discovery,
base_payload_archive_root,
base_locks_path,
delta_payload_archive_root,
delta_locks_path,
base_validation_time,
validation_time,
config,
None,
)
}
pub fn run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit_with_timing(
store: &crate::storage::RocksStore,
policy: &crate::policy::Policy,
tal_bytes: &[u8],
ta_der: &[u8],
resolved_ta_uri: Option<&Url>,
base_payload_archive_root: &std::path::Path,
base_locks_path: &std::path::Path,
delta_payload_archive_root: &std::path::Path,
delta_locks_path: &std::path::Path,
base_validation_time: time::OffsetDateTime,
validation_time: time::OffsetDateTime,
config: &TreeRunConfig,
timing: &TimingHandle,
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
let _tal = timing.span_phase("tal_bootstrap");
let discovery =
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
drop(_tal);
run_payload_delta_replay_audit_inner(
store,
policy,
discovery,
base_payload_archive_root,
base_locks_path,
delta_payload_archive_root,
delta_locks_path,
base_validation_time,
validation_time,
config,
Some(timing.clone()),
)
}
#[cfg(test)]
mod replay_api_tests {
use super::*;
@@ -587,6 +832,58 @@ mod replay_api_tests {
(tal_bytes, ta_der, archive_root, locks_path, validation_time)
}
fn apnic_multi_rir_replay_inputs() -> (
Vec<u8>,
Vec<u8>,
std::path::PathBuf,
std::path::PathBuf,
time::OffsetDateTime,
) {
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der =
std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let archive_root =
std::path::PathBuf::from("../../rpki/target/live/20260316-112341-multi-final3/apnic/base-payload-archive");
let locks_path =
std::path::PathBuf::from("../../rpki/target/live/20260316-112341-multi-final3/apnic/base-locks.json");
let validation_time = time::OffsetDateTime::parse("2026-03-16T11:49:48+08:00", &Rfc3339)
.expect("parse validation time");
(tal_bytes, ta_der, archive_root, locks_path, validation_time)
}
fn apnic_delta_replay_inputs() -> (
Vec<u8>,
Vec<u8>,
std::path::PathBuf,
std::path::PathBuf,
std::path::PathBuf,
std::path::PathBuf,
time::OffsetDateTime,
) {
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der =
std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let root =
std::path::PathBuf::from("target/live/apnic_delta_demo/20260315-170223-autoplay");
let base_archive = root.join("base-payload-archive");
let base_locks = root.join("base-locks.json");
let delta_archive = root.join("payload-delta-archive");
let delta_locks = root.join("locks-delta.json");
let validation_time = time::OffsetDateTime::parse("2026-03-15T10:00:00Z", &Rfc3339)
.expect("parse validation time");
(
tal_bytes,
ta_der,
base_archive,
base_locks,
delta_archive,
delta_locks,
validation_time,
)
}
#[test]
fn payload_replay_api_reports_setup_error_for_missing_archive() {
let temp = tempfile::tempdir().expect("tempdir");
@@ -656,6 +953,37 @@ mod replay_api_tests {
);
}
#[test]
fn payload_replay_api_root_only_apnic_multi_rir_bundle_runs_with_lenient_rsync_modules() {
let temp = tempfile::tempdir().expect("tempdir");
let store = crate::storage::RocksStore::open(&temp.path().join("db")).expect("open db");
let (tal_bytes, ta_der, archive_root, locks_path, validation_time) =
apnic_multi_rir_replay_inputs();
assert!(archive_root.is_dir(), "payload replay archive missing: {}", archive_root.display());
assert!(locks_path.is_file(), "payload replay locks missing: {}", locks_path.display());
let out = run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
&store,
&crate::policy::Policy::default(),
&tal_bytes,
&ta_der,
None,
&archive_root,
&locks_path,
validation_time,
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run replay root-only audit");
assert_eq!(out.tree.instances_processed, 1);
assert_eq!(out.tree.instances_failed, 0);
assert_eq!(out.publication_points.len(), 1);
}
#[test]
fn payload_replay_api_root_only_apnic_archive_runs_with_timing() {
let temp = tempfile::tempdir().expect("tempdir");
@@ -714,4 +1042,184 @@ mod replay_api_tests {
>= 1
);
}
#[test]
fn payload_delta_replay_api_rejects_base_locks_sha_mismatch() {
let temp = tempfile::tempdir().expect("tempdir");
let store = crate::storage::RocksStore::open(&temp.path().join("db")).expect("open db");
let (
tal_bytes,
ta_der,
base_archive,
_base_locks,
delta_archive,
delta_locks,
validation_time,
) = apnic_delta_replay_inputs();
let wrong_base_locks = temp.path().join("wrong-base-locks.json");
std::fs::write(&wrong_base_locks, b"wrong-base-locks").expect("write wrong base locks");
let err = run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
&store,
&crate::policy::Policy::default(),
&tal_bytes,
&ta_der,
None,
&base_archive,
&wrong_base_locks,
&delta_archive,
&delta_locks,
validation_time,
validation_time,
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.unwrap_err();
assert!(matches!(err, RunTreeFromTalError::Replay(_)), "{err}");
}
#[test]
fn payload_delta_replay_api_reports_setup_error_for_missing_inputs() {
let temp = tempfile::tempdir().expect("tempdir");
let store = crate::storage::RocksStore::open(&temp.path().join("db")).expect("open db");
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der =
std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let err = run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
&store,
&crate::policy::Policy::default(),
&tal_bytes,
&ta_der,
None,
std::path::Path::new("tests/fixtures/missing-base-archive"),
std::path::Path::new("tests/fixtures/missing-base-locks.json"),
std::path::Path::new("tests/fixtures/missing-delta-archive"),
std::path::Path::new("tests/fixtures/missing-delta-locks.json"),
time::OffsetDateTime::now_utc(),
time::OffsetDateTime::now_utc(),
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.unwrap_err();
assert!(matches!(err, RunTreeFromTalError::Replay(_)), "{err}");
}
#[test]
fn payload_delta_replay_api_root_only_apnic_bundle_runs() {
let temp = tempfile::tempdir().expect("tempdir");
let store = crate::storage::RocksStore::open(&temp.path().join("db")).expect("open db");
let (
tal_bytes,
ta_der,
base_archive,
base_locks,
delta_archive,
delta_locks,
validation_time,
) = apnic_delta_replay_inputs();
assert!(
base_archive.is_dir(),
"base archive missing: {}",
base_archive.display()
);
assert!(
base_locks.is_file(),
"base locks missing: {}",
base_locks.display()
);
assert!(
delta_archive.is_dir(),
"delta archive missing: {}",
delta_archive.display()
);
assert!(
delta_locks.is_file(),
"delta locks missing: {}",
delta_locks.display()
);
let out = run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
&store,
&crate::policy::Policy::default(),
&tal_bytes,
&ta_der,
None,
&base_archive,
&base_locks,
&delta_archive,
&delta_locks,
validation_time,
validation_time,
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run delta replay root-only audit");
assert_eq!(out.tree.instances_processed, 1);
assert_eq!(out.tree.instances_failed, 0);
assert_eq!(out.publication_points.len(), 1);
}
#[test]
fn payload_delta_replay_api_root_only_apnic_bundle_runs_with_timing() {
let temp = tempfile::tempdir().expect("tempdir");
let db_path = temp.path().join("db");
let store = crate::storage::RocksStore::open(&db_path).expect("open db");
let (
tal_bytes,
ta_der,
base_archive,
base_locks,
delta_archive,
delta_locks,
validation_time,
) = apnic_delta_replay_inputs();
let timing = TimingHandle::new(TimingMeta {
recorded_at_utc_rfc3339: "2026-03-16T00:00:00Z".to_string(),
validation_time_utc_rfc3339: "2026-03-15T10:00:00Z".to_string(),
tal_url: None,
db_path: Some(db_path.to_string_lossy().into_owned()),
});
let out = run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit_with_timing(
&store,
&crate::policy::Policy::default(),
&tal_bytes,
&ta_der,
None,
&base_archive,
&base_locks,
&delta_archive,
&delta_locks,
validation_time,
validation_time,
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
&timing,
)
.expect("run delta replay root-only audit with timing");
assert_eq!(out.tree.instances_processed, 1);
let timing_json = temp.path().join("timing_delta_replay.json");
timing
.write_json(&timing_json, 20)
.expect("write timing json");
let json: serde_json::Value =
serde_json::from_slice(&std::fs::read(&timing_json).expect("read timing json"))
.expect("parse timing json");
assert_eq!(
json["phases"]["payload_delta_replay_base_total"]["count"].as_u64(),
Some(1)
);
assert_eq!(
json["phases"]["payload_delta_replay_target_total"]["count"].as_u64(),
Some(1)
);
}
}

View File

@@ -12,6 +12,7 @@ use crate::data_model::roa::{RoaAfi, RoaObject};
use crate::fetch::rsync::RsyncFetcher;
use crate::policy::Policy;
use crate::replay::archive::ReplayArchiveIndex;
use crate::replay::delta_archive::ReplayDeltaArchiveIndex;
use crate::report::{RfcRef, Warning};
use crate::storage::{
AuditRuleIndexEntry, AuditRuleKind, PackFile, PackTime, RawByHashEntry, RocksStore,
@@ -19,7 +20,9 @@ use crate::storage::{
VcirAuditSummary, VcirChildEntry, VcirInstanceGate, VcirLocalOutput, VcirOutputType,
VcirRelatedArtifact, VcirSummary,
};
use crate::sync::repo::{sync_publication_point, sync_publication_point_replay};
use crate::sync::repo::{
sync_publication_point, sync_publication_point_replay, sync_publication_point_replay_delta,
};
use crate::sync::rrdp::Fetcher;
use crate::validation::ca_instance::ca_instance_uris_from_ca_certificate;
use crate::validation::ca_path::{
@@ -51,6 +54,7 @@ pub struct Rpkiv1PublicationPointRunner<'a> {
pub timing: Option<TimingHandle>,
pub download_log: Option<DownloadLogHandle>,
pub replay_archive_index: Option<Arc<ReplayArchiveIndex>>,
pub replay_delta_index: Option<Arc<ReplayDeltaArchiveIndex>>,
/// In-run RRDP dedup: when RRDP is enabled, only sync each `rrdp_notification_uri` once per run.
///
/// - If RRDP succeeded for a repo, later publication points referencing that same RRDP repo
@@ -153,7 +157,18 @@ impl<'a> PublicationPointRunner for Rpkiv1PublicationPointRunner<'a> {
.map(|t| t.span_phase("repo_sync_total"));
let _repo_span = self.timing.as_ref().map(|t| t.span_rrdp_repo(repo_key));
match if let Some(replay_index) = self.replay_archive_index.as_ref() {
match if let Some(delta_index) = self.replay_delta_index.as_ref() {
sync_publication_point_replay_delta(
self.store,
delta_index,
effective_notification_uri,
&ca.rsync_base_uri,
self.http_fetcher,
self.rsync_fetcher,
self.timing.as_ref(),
self.download_log.as_ref(),
)
} else if let Some(replay_index) = self.replay_archive_index.as_ref() {
sync_publication_point_replay(
self.store,
replay_index,
@@ -2873,6 +2888,7 @@ authorityKeyIdentifier = keyid:always
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: false,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: false,
@@ -3040,6 +3056,7 @@ authorityKeyIdentifier = keyid:always
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: false,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,
@@ -3118,6 +3135,7 @@ authorityKeyIdentifier = keyid:always
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: false,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: false,
@@ -3142,6 +3160,7 @@ authorityKeyIdentifier = keyid:always
timing: None,
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: false,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: false,
@@ -4127,6 +4146,7 @@ authorityKeyIdentifier = keyid:always
timing: Some(timing.clone()),
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: true,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: false,
@@ -4154,6 +4174,7 @@ authorityKeyIdentifier = keyid:always
timing: Some(timing),
download_log: None,
replay_archive_index: None,
replay_delta_index: None,
rrdp_dedup: false,
rrdp_repo_cache: Mutex::new(HashMap::new()),
rsync_dedup: true,