datastore: implement Iterator for backup group listing
While currently it's still only used in a collected() way, most call sites can be switched over to use the iterator directly, as often they already convert the not-so-cheap, in-memory vector back in .into_iter() anyway. somewhat also preparatory (yak shaving) work for namespaces Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
72f8154571
commit
de015ce7e1
|
@ -554,34 +554,7 @@ impl DataStore {
|
||||||
|
|
||||||
/// Get a in-memory vector for all top-level backup groups of a datatstore
|
/// Get a in-memory vector for all top-level backup groups of a datatstore
|
||||||
pub fn list_backup_groups(&self) -> Result<Vec<BackupGroup>, Error> {
|
pub fn list_backup_groups(&self) -> Result<Vec<BackupGroup>, Error> {
|
||||||
let mut list = Vec::new();
|
ListGroups::new(self.base_path())?.collect()
|
||||||
|
|
||||||
proxmox_sys::fs::scandir(
|
|
||||||
libc::AT_FDCWD,
|
|
||||||
&self.base_path(),
|
|
||||||
&BACKUP_TYPE_REGEX,
|
|
||||||
|l0_fd, backup_type, file_type| {
|
|
||||||
if file_type != nix::dir::Type::Directory {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
proxmox_sys::fs::scandir(
|
|
||||||
l0_fd,
|
|
||||||
backup_type,
|
|
||||||
&BACKUP_ID_REGEX,
|
|
||||||
|_, backup_id, file_type| {
|
|
||||||
if file_type != nix::dir::Type::Directory {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
list.push(BackupGroup::new(backup_type, backup_id));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(list)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_images(&self) -> Result<Vec<PathBuf>, Error> {
|
pub fn list_images(&self) -> Result<Vec<PathBuf>, Error> {
|
||||||
|
@ -1065,3 +1038,75 @@ impl DataStore {
|
||||||
Ok(chunk_list)
|
Ok(chunk_list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A iterator for a (single) level of Backup Groups
|
||||||
|
pub struct ListGroups {
|
||||||
|
type_fd: proxmox_sys::fs::ReadDir,
|
||||||
|
id_state: Option<(String, proxmox_sys::fs::ReadDir)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListGroups {
|
||||||
|
pub fn new(base_path: PathBuf) -> Result<Self, Error> {
|
||||||
|
Ok(ListGroups {
|
||||||
|
type_fd: proxmox_sys::fs::read_subdir(libc::AT_FDCWD, &base_path)?,
|
||||||
|
id_state: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ListGroups {
|
||||||
|
type Item = Result<BackupGroup, Error>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
loop {
|
||||||
|
if let Some((ref group_type, ref mut id_fd)) = self.id_state {
|
||||||
|
let item = match id_fd.next() {
|
||||||
|
Some(item) => item,
|
||||||
|
None => {
|
||||||
|
self.id_state = None;
|
||||||
|
continue; // exhausted all IDs for the current group type, try others
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match item {
|
||||||
|
Ok(ref entry) => {
|
||||||
|
if let Ok(name) = entry.file_name().to_str() {
|
||||||
|
match entry.file_type() {
|
||||||
|
Some(nix::dir::Type::Directory) => {} // OK
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
if BACKUP_ID_REGEX.is_match(name) {
|
||||||
|
return Some(Ok(BackupGroup::new(group_type, name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; // file did not match regex or isn't valid utf-8
|
||||||
|
}
|
||||||
|
Err(err) => return Some(Err(err)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let item = self.type_fd.next()?;
|
||||||
|
match item {
|
||||||
|
Ok(ref entry) => {
|
||||||
|
if let Ok(name) = entry.file_name().to_str() {
|
||||||
|
match entry.file_type() {
|
||||||
|
Some(nix::dir::Type::Directory) => {} // OK
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
if BACKUP_TYPE_REGEX.is_match(name) {
|
||||||
|
// found a backup group type, descend into it to scan all IDs in it
|
||||||
|
// by switching to the id-state branch
|
||||||
|
let base_fd = entry.parent_fd();
|
||||||
|
let id_dirfd = match proxmox_sys::fs::read_subdir(base_fd, name) {
|
||||||
|
Ok(dirfd) => dirfd,
|
||||||
|
Err(err) => return Some(Err(err.into())),
|
||||||
|
};
|
||||||
|
self.id_state = Some((name.to_owned(), id_dirfd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; // file did not match regex or isn't valid utf-8
|
||||||
|
}
|
||||||
|
Err(err) => return Some(Err(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ pub use manifest::BackupManifest;
|
||||||
pub use store_progress::StoreProgress;
|
pub use store_progress::StoreProgress;
|
||||||
|
|
||||||
mod datastore;
|
mod datastore;
|
||||||
pub use datastore::{check_backup_owner, DataStore};
|
pub use datastore::{check_backup_owner, DataStore, ListGroups};
|
||||||
|
|
||||||
mod snapshot_reader;
|
mod snapshot_reader;
|
||||||
pub use snapshot_reader::SnapshotReader;
|
pub use snapshot_reader::SnapshotReader;
|
||||||
|
|
Loading…
Reference in New Issue