use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use rpki::uri;
#[derive(Clone, Debug)]
pub struct DumpRegistry {
base_dir: PathBuf,
rrdp_uris: HashMap<uri::Https, String>,
rrdp_dirs: HashSet<String>,
}
impl DumpRegistry {
pub fn new(base_dir: PathBuf) -> Self {
DumpRegistry {
base_dir,
rrdp_uris: HashMap::new(),
rrdp_dirs: HashSet::new(),
}
}
pub fn base_dir(&self) -> &Path {
&self.base_dir
}
pub fn get_repo_path(
&mut self, rpki_notify: Option<&uri::Https>
) -> PathBuf {
if let Some(rpki_notify) = rpki_notify {
if let Some(path) = self.rrdp_uris.get(rpki_notify) {
self.base_dir.join(path)
}
else {
self.make_path(rpki_notify)
}
}
else {
self.base_dir.join("rsync")
}
}
fn make_path(&mut self, uri: &uri::Https) -> PathBuf {
let authority = uri.canonical_authority();
if !self.rrdp_dirs.contains(authority.as_ref()) {
self.rrdp_dirs.insert(authority.as_ref().into());
self.rrdp_uris.insert(uri.clone(), authority.as_ref().into());
self.base_dir.join(authority.as_ref())
}
else {
let mut i = 1;
loop {
let name = format!("{}-{}", authority, i);
if !self.rrdp_dirs.contains(&name) {
self.rrdp_dirs.insert(name.clone());
self.rrdp_uris.insert(uri.clone(), name.clone());
return self.base_dir.join(name)
}
i += 1
}
}
}
pub fn rrdp_uris(
&self
) -> impl Iterator<Item = (&'_ uri::Https, &'_ str)> + '_ {
self.rrdp_uris.iter().map(|(key, value)| (key, value.as_str()))
}
}