rustic_core/repofile/configfile.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
use serde_derive::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use crate::{
backend::FileType, blob::BlobType, define_new_id_struct, error::ConfigFileErrorKind,
impl_repofile, repofile::RepoFile, RusticResult,
};
pub(super) mod constants {
pub(super) const KB: u32 = 1024;
pub(super) const MB: u32 = 1024 * KB;
/// Default Tree size
pub(super) const DEFAULT_TREE_SIZE: u32 = 4 * MB;
/// Default Data size
pub(super) const DEFAULT_DATA_SIZE: u32 = 32 * MB;
/// the default factor used for repo-size dependent pack size.
/// 32 * sqrt(reposize in bytes) = 1 MB * sqrt(reposize in GB)
pub(super) const DEFAULT_GROW_FACTOR: u32 = 32;
/// The default maximum targeted pack size.
pub(super) const DEFAULT_SIZE_LIMIT: u32 = u32::MAX;
/// The default minimum percentage of targeted pack size.
pub(super) const DEFAULT_MIN_PERCENTAGE: u32 = 30;
}
define_new_id_struct!(RepositoryId, "repository");
impl_repofile!(ConfigId, FileType::Config, ConfigFile);
#[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
/// The config file describes all repository-wide information.
///
/// It is usually saved in the repository as `config`
pub struct ConfigFile {
/// Repository version. Currently 1 and 2 are supported
pub version: u32,
/// The [`Id`] identifying the repsitory
pub id: RepositoryId,
/// The chunker polynomial used to chunk data
pub chunker_polynomial: String,
/// Marker if this is a hot repository. If not set, this is no hot repository
///
/// # Note
///
/// When using hot/cold repositories, this is only set within the hot part of the repository.
pub is_hot: Option<bool>,
/// Marker if this is a append-only repository.
///
/// # Note
///
/// Commands which are not append-only won't run once this is set.
pub append_only: Option<bool>,
/// Compression level
///
/// # Note
///
/// `Some(0)` means no compression. If not set, use the default compression:
/// * for repository version 1, use no compression (as not supported)
/// * for repository version 2, use the zstd default compression
pub compression: Option<i32>,
/// Size of tree packs. This will be enhanced by the `treepack_growfactor` depending on the repository size
///
/// If not set, defaults to 4 MiB
pub treepack_size: Option<u32>,
/// Grow factor to increase size of tree packs depending on the repository size
///
/// If not set, defaults to `32`
pub treepack_growfactor: Option<u32>,
/// Maximum targeted tree pack size.
pub treepack_size_limit: Option<u32>,
/// Size of data packs. This will be enhanced by the `datapack_growfactor` depending on the repository size
///
/// If not set, defaults to `32 MiB`
pub datapack_size: Option<u32>,
/// Grow factor to increase size of data packs depending on the repository size
///
/// If not set, defaults to `32`
pub datapack_growfactor: Option<u32>,
/// maximum targeted data pack size.
pub datapack_size_limit: Option<u32>,
/// Tolerate pack sizes which are larger than given percentage of targeted pack size
///
/// If not set, defaults to `30`
pub min_packsize_tolerate_percent: Option<u32>,
/// Tolerate pack sizes which are smaller than given percentage of targeted pack size
///
/// If not set or set to `0` this is unlimited.
pub max_packsize_tolerate_percent: Option<u32>,
/// Do an extra verification by decompressing/decrypting all data before uploading to the repository
pub extra_verify: Option<bool>,
}
impl ConfigFile {
#[must_use]
/// Creates a new `ConfigFile`.
///
/// # Arguments
///
/// * `version` - The version of the repository
/// * `id` - The id of the repository
/// * `poly` - The chunker polynomial
pub fn new(version: u32, id: RepositoryId, poly: u64) -> Self {
Self {
version,
id,
chunker_polynomial: format!("{poly:x}"),
..Self::default()
}
}
/// Get the chunker polynomial
///
/// # Errors
///
/// * [`ConfigFileErrorKind::ParsingFailedForPolynomial`] - If the polynomial could not be parsed
///
/// [`ConfigFileErrorKind::ParsingFailedForPolynomial`]: crate::error::ConfigFileErrorKind::ParsingFailedForPolynomial
pub fn poly(&self) -> RusticResult<u64> {
Ok(u64::from_str_radix(&self.chunker_polynomial, 16)
.map_err(ConfigFileErrorKind::ParsingFailedForPolynomial)?)
}
/// Get the compression level
///
/// # Errors
///
/// * [`ConfigFileErrorKind::ConfigVersionNotSupported`] - If the version is not supported
///
/// [`ConfigFileErrorKind::ConfigVersionNotSupported`]: crate::error::ConfigFileErrorKind::ConfigVersionNotSupported
pub fn zstd(&self) -> RusticResult<Option<i32>> {
match (self.version, self.compression) {
(1, _) | (2, Some(0)) => Ok(None),
(2, None) => Ok(Some(0)), // use default (=0) zstd compression
(2, Some(c)) => Ok(Some(c)),
_ => Err(ConfigFileErrorKind::ConfigVersionNotSupported.into()),
}
}
/// Get wheter an extra verification (decompressing/decrypting data before writing to the repository) should be performed.
#[must_use]
pub fn extra_verify(&self) -> bool {
self.extra_verify.unwrap_or(true) // default is to do the extra check
}
/// Get pack size parameter
///
/// # Arguments
///
/// * `blob` - The blob type to get the pack size parameters for
///
/// # Returns
///
/// A tuple containing the pack size, the grow factor and the size limit
#[must_use]
pub fn packsize(&self, blob: BlobType) -> (u32, u32, u32) {
match blob {
BlobType::Tree => (
self.treepack_size.unwrap_or(constants::DEFAULT_TREE_SIZE),
self.treepack_growfactor
.unwrap_or(constants::DEFAULT_GROW_FACTOR),
self.treepack_size_limit
.unwrap_or(constants::DEFAULT_SIZE_LIMIT),
),
BlobType::Data => (
self.datapack_size.unwrap_or(constants::DEFAULT_DATA_SIZE),
self.datapack_growfactor
.unwrap_or(constants::DEFAULT_GROW_FACTOR),
self.datapack_size_limit
.unwrap_or(constants::DEFAULT_SIZE_LIMIT),
),
}
}
/// Get pack size toleration limits
///
/// # Returns
///
///
#[must_use]
pub fn packsize_ok_percents(&self) -> (u32, u32) {
(
self.min_packsize_tolerate_percent
.unwrap_or(constants::DEFAULT_MIN_PERCENTAGE),
match self.max_packsize_tolerate_percent {
None | Some(0) => u32::MAX,
Some(percent) => percent,
},
)
}
}