From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 1682C1FF16C for ; Tue, 3 Sep 2024 14:34:15 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E601597D3; Tue, 3 Sep 2024 14:34:43 +0200 (CEST) From: Hannes Laimer To: pbs-devel@lists.proxmox.com Date: Tue, 3 Sep 2024 14:33:56 +0200 Message-Id: <20240903123401.91513-6-h.laimer@proxmox.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240903123401.91513-1-h.laimer@proxmox.com> References: <20240903123401.91513-1-h.laimer@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.018 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pbs-devel] [PATCH proxmox-backup RFC 05/10] backup_info: add generics and separate functions into impl blocks X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Backup Server development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pbs-devel-bounces@lists.proxmox.com Sender: "pbs-devel" Signed-off-by: Hannes Laimer --- pbs-datastore/src/backup_info.rs | 179 ++++++++++++++++--------------- 1 file changed, 93 insertions(+), 86 deletions(-) diff --git a/pbs-datastore/src/backup_info.rs b/pbs-datastore/src/backup_info.rs index 414ec878..d353f9d6 100644 --- a/pbs-datastore/src/backup_info.rs +++ b/pbs-datastore/src/backup_info.rs @@ -12,6 +12,7 @@ use pbs_api_types::{ }; use pbs_config::{open_backup_lockfile, BackupLockGuard}; +use crate::chunk_store::{CanRead, CanWrite}; use crate::manifest::{ BackupManifest, CLIENT_LOG_BLOB_NAME, MANIFEST_BLOB_NAME, MANIFEST_LOCK_NAME, }; @@ -49,14 +50,14 @@ impl BackupGroupDeleteStats { /// BackupGroup is a directory containing a list of BackupDir #[derive(Clone)] -pub struct BackupGroup { - store: Arc, +pub struct BackupGroup { + store: Arc>, ns: BackupNamespace, group: pbs_api_types::BackupGroup, } -impl fmt::Debug for BackupGroup { +impl fmt::Debug for BackupGroup { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BackupGroup") .field("store", &self.store.name()) @@ -66,9 +67,9 @@ impl fmt::Debug for BackupGroup { } } -impl BackupGroup { +impl BackupGroup { pub(crate) fn new( - store: Arc, + store: Arc>, ns: BackupNamespace, group: pbs_api_types::BackupGroup, ) -> Self { @@ -106,14 +107,30 @@ impl BackupGroup { path.push(&self.group.id); path } + pub fn matches(&self, filter: &GroupFilter) -> bool { + self.group.matches(filter) + } + + pub fn backup_dir(&self, time: i64) -> Result, Error> { + BackupDir::with_group(self.clone(), time) + } + + pub fn backup_dir_with_rfc3339>( + &self, + time_string: D, + ) -> Result, Error> { + BackupDir::with_rfc3339(self.clone(), time_string.into()) + } +} +impl BackupGroup { /// Simple check whether a group exists. This does not check whether there are any snapshots, /// but rather it simply checks whether the directory exists. pub fn exists(&self) -> bool { self.full_group_path().exists() } - pub fn list_backups(&self) -> Result, Error> { + pub fn list_backups(&self) -> Result>, Error> { let mut list = vec![]; let path = self.full_group_path(); @@ -145,7 +162,7 @@ impl BackupGroup { } /// Finds the latest backup inside a backup group - pub fn last_backup(&self, only_finished: bool) -> Result, Error> { + pub fn last_backup(&self, only_finished: bool) -> Result>, Error> { let backups = self.list_backups()?; Ok(backups .into_iter() @@ -206,23 +223,23 @@ impl BackupGroup { Ok(last) } - pub fn matches(&self, filter: &GroupFilter) -> bool { - self.group.matches(filter) - } - - pub fn backup_dir(&self, time: i64) -> Result { - BackupDir::with_group(self.clone(), time) + pub fn iter_snapshots(&self) -> Result, Error> { + crate::ListSnapshots::new(self.clone()) } - pub fn backup_dir_with_rfc3339>( - &self, - time_string: T, - ) -> Result { - BackupDir::with_rfc3339(self.clone(), time_string.into()) + /// Returns the backup owner. + /// + /// The backup owner is the entity who first created the backup group. + pub fn get_owner(&self) -> Result { + self.store.get_owner(&self.ns, self.as_ref()) } +} - pub fn iter_snapshots(&self) -> Result { - crate::ListSnapshots::new(self.clone()) +impl BackupGroup { + /// Set the backup owner. + pub fn set_owner(&self, auth_id: &Authid, force: bool) -> Result<(), Error> { + self.store + .set_owner(&self.ns, self.as_ref(), auth_id, force) } /// Destroy the group inclusive all its backup snapshots (BackupDir's) @@ -254,49 +271,36 @@ impl BackupGroup { Ok(delete_stats) } - - /// Returns the backup owner. - /// - /// The backup owner is the entity who first created the backup group. - pub fn get_owner(&self) -> Result { - self.store.get_owner(&self.ns, self.as_ref()) - } - - /// Set the backup owner. - pub fn set_owner(&self, auth_id: &Authid, force: bool) -> Result<(), Error> { - self.store - .set_owner(&self.ns, self.as_ref(), auth_id, force) - } } -impl AsRef for BackupGroup { +impl AsRef for BackupGroup { #[inline] fn as_ref(&self) -> &pbs_api_types::BackupNamespace { &self.ns } } -impl AsRef for BackupGroup { +impl AsRef for BackupGroup { #[inline] fn as_ref(&self) -> &pbs_api_types::BackupGroup { &self.group } } -impl From<&BackupGroup> for pbs_api_types::BackupGroup { - fn from(group: &BackupGroup) -> pbs_api_types::BackupGroup { +impl From<&BackupGroup> for pbs_api_types::BackupGroup { + fn from(group: &BackupGroup) -> pbs_api_types::BackupGroup { group.group.clone() } } -impl From for pbs_api_types::BackupGroup { - fn from(group: BackupGroup) -> pbs_api_types::BackupGroup { +impl From> for pbs_api_types::BackupGroup { + fn from(group: BackupGroup) -> pbs_api_types::BackupGroup { group.group } } -impl From for BackupGroup { - fn from(dir: BackupDir) -> BackupGroup { +impl From> for BackupGroup { + fn from(dir: BackupDir) -> BackupGroup { BackupGroup { store: dir.store, ns: dir.ns, @@ -305,8 +309,8 @@ impl From for BackupGroup { } } -impl From<&BackupDir> for BackupGroup { - fn from(dir: &BackupDir) -> BackupGroup { +impl From<&BackupDir> for BackupGroup { + fn from(dir: &BackupDir) -> BackupGroup { BackupGroup { store: Arc::clone(&dir.store), ns: dir.ns.clone(), @@ -319,15 +323,15 @@ impl From<&BackupDir> for BackupGroup { /// /// We also call this a backup snaphost. #[derive(Clone)] -pub struct BackupDir { - store: Arc, +pub struct BackupDir { + store: Arc>, ns: BackupNamespace, dir: pbs_api_types::BackupDir, // backup_time as rfc3339 backup_time_string: String, } -impl fmt::Debug for BackupDir { +impl fmt::Debug for BackupDir { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BackupDir") .field("store", &self.store.name()) @@ -338,19 +342,21 @@ impl fmt::Debug for BackupDir { } } -impl BackupDir { +impl BackupDir { /// Temporarily used for tests. #[doc(hidden)] pub fn new_test(dir: pbs_api_types::BackupDir) -> Self { Self { - store: unsafe { DataStore::new_test() }, + store: DataStore::new_test(), backup_time_string: Self::backup_time_to_string(dir.time).unwrap(), ns: BackupNamespace::root(), dir, } } +} - pub(crate) fn with_group(group: BackupGroup, backup_time: i64) -> Result { +impl BackupDir { + pub(crate) fn with_group(group: BackupGroup, backup_time: i64) -> Result { let backup_time_string = Self::backup_time_to_string(backup_time)?; Ok(Self { store: group.store, @@ -361,7 +367,7 @@ impl BackupDir { } pub(crate) fn with_rfc3339( - group: BackupGroup, + group: BackupGroup, backup_time_string: String, ) -> Result { let backup_time = proxmox_time::parse_rfc3339(&backup_time_string)?; @@ -436,18 +442,6 @@ impl BackupDir { proxmox_time::epoch_to_rfc3339_utc(backup_time) } - /// load a `DataBlob` from this snapshot's backup dir. - pub fn load_blob(&self, filename: &str) -> Result { - let mut path = self.full_path(); - path.push(filename); - - proxmox_lang::try_block!({ - let mut file = std::fs::File::open(&path)?; - DataBlob::load_from_reader(&mut file) - }) - .map_err(|err| format_err!("unable to load blob '{:?}' - {}", path, err)) - } - /// Returns the filename to lock a manifest /// /// Also creates the basedir. The lockfile is located in @@ -502,19 +496,25 @@ impl BackupDir { } /// Get the datastore. - pub fn datastore(&self) -> &Arc { + pub fn datastore(&self) -> &Arc> { &self.store } +} +impl BackupDir { + /// load a `DataBlob` from this snapshot's backup dir. + pub fn load_blob(&self, filename: &str) -> Result { + let mut path = self.full_path(); + path.push(filename); - /// Returns the backup owner. - /// - /// The backup owner is the entity who first created the backup group. - pub fn get_owner(&self) -> Result { - self.store.get_owner(&self.ns, self.as_ref()) + proxmox_lang::try_block!({ + let mut file = std::fs::File::open(&path)?; + DataBlob::load_from_reader(&mut file) + }) + .map_err(|err| format_err!("unable to load blob '{:?}' - {}", path, err)) } /// Lock the snapshot and open a reader. - pub fn locked_reader(&self) -> Result { + pub fn locked_reader(&self) -> Result, Error> { crate::SnapshotReader::new_do(self.clone()) } @@ -525,7 +525,15 @@ impl BackupDir { let manifest = BackupManifest::try_from(blob)?; Ok((manifest, raw_size)) } + /// Returns the backup owner. + /// + /// The backup owner is the entity who first created the backup group. + pub fn get_owner(&self) -> Result { + self.store.get_owner(&self.ns, self.as_ref()) + } +} +impl BackupDir { /// Update the manifest of the specified snapshot. Never write a manifest directly, /// only use this method - anything else may break locking guarantees. pub fn update_manifest( @@ -584,62 +592,61 @@ impl BackupDir { Ok(()) } } - -impl AsRef for BackupDir { +impl AsRef for BackupDir { fn as_ref(&self) -> &pbs_api_types::BackupNamespace { &self.ns } } -impl AsRef for BackupDir { +impl AsRef for BackupDir { fn as_ref(&self) -> &pbs_api_types::BackupDir { &self.dir } } -impl AsRef for BackupDir { +impl AsRef for BackupDir { fn as_ref(&self) -> &pbs_api_types::BackupGroup { &self.dir.group } } -impl From<&BackupDir> for pbs_api_types::BackupGroup { - fn from(dir: &BackupDir) -> pbs_api_types::BackupGroup { +impl From<&BackupDir> for pbs_api_types::BackupGroup { + fn from(dir: &BackupDir) -> pbs_api_types::BackupGroup { dir.dir.group.clone() } } -impl From for pbs_api_types::BackupGroup { - fn from(dir: BackupDir) -> pbs_api_types::BackupGroup { +impl From> for pbs_api_types::BackupGroup { + fn from(dir: BackupDir) -> pbs_api_types::BackupGroup { dir.dir.group } } -impl From<&BackupDir> for pbs_api_types::BackupDir { - fn from(dir: &BackupDir) -> pbs_api_types::BackupDir { +impl From<&BackupDir> for pbs_api_types::BackupDir { + fn from(dir: &BackupDir) -> pbs_api_types::BackupDir { dir.dir.clone() } } -impl From for pbs_api_types::BackupDir { - fn from(dir: BackupDir) -> pbs_api_types::BackupDir { +impl From> for pbs_api_types::BackupDir { + fn from(dir: BackupDir) -> pbs_api_types::BackupDir { dir.dir } } /// Detailed Backup Information, lists files inside a BackupDir #[derive(Clone, Debug)] -pub struct BackupInfo { +pub struct BackupInfo { /// the backup directory - pub backup_dir: BackupDir, + pub backup_dir: BackupDir, /// List of data files pub files: Vec, /// Protection Status pub protected: bool, } -impl BackupInfo { - pub fn new(backup_dir: BackupDir) -> Result { +impl BackupInfo { + pub fn new(backup_dir: BackupDir) -> Result { let path = backup_dir.full_path(); let files = list_backup_files(libc::AT_FDCWD, &path)?; @@ -652,7 +659,7 @@ impl BackupInfo { }) } - pub fn sort_list(list: &mut [BackupInfo], ascendending: bool) { + pub fn sort_list(list: &mut [BackupInfo], ascendending: bool) { if ascendending { // oldest first list.sort_unstable_by(|a, b| a.backup_dir.dir.time.cmp(&b.backup_dir.dir.time)); -- 2.39.2 _______________________________________________ pbs-devel mailing list pbs-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel