/// Inventory and accounting functions for storage dashboards.
pub(all) struct StorageReport {
logical_bytes : Int
physical_bytes : Int
chunk_count : Int
unique_chunks : Int
deduplicated_bytes : Int
manifest_bytes : Int
} derive(Show)
pub fn StorageReport::logical(self : StorageReport) -> Int { self.logical_bytes }
pub fn StorageReport::physical(self : StorageReport) -> Int { self.physical_bytes }
pub fn StorageReport::chunks(self : StorageReport) -> Int { self.chunk_count }
pub fn StorageReport::unique(self : StorageReport) -> Int { self.unique_chunks }
pub fn StorageReport::saved(self : StorageReport) -> Int { self.deduplicated_bytes }
pub fn StorageReport::manifest(self : StorageReport) -> Int { self.manifest_bytes }
pub fn inspect_storage(store : ChunkStore, manifest : Manifest) -> StorageReport {
let refs = manifest.references()
let unique = unique_digests(refs.map(r => r.id()))
let mut physical = 0
for digest in unique {
match store.get(digest) {
Some(data) => physical = physical + data.length()
None => ()
}
}
let logical = manifest.size()
{ logical_bytes: logical, physical_bytes: physical, chunk_count: refs.length(), unique_chunks: unique_digests(refs.map(r => r.id())).length(), deduplicated_bytes: logical - physical, manifest_bytes: encode_manifest(manifest).to_bytes().length() }
}
pub fn storage_report_line(report : StorageReport) -> String {
"logical={report.logical()} physical={report.physical()} chunks={report.chunks()} unique={report.unique()} saved={report.saved()}"
}
pub fn storage_is_consistent(report : StorageReport) -> Bool {
report.logical() >= report.physical() && report.unique() <= report.chunks()
}
pub fn store_logical_size(store : ChunkStore, manifest : Manifest) -> Int {
let report = inspect_storage(store, manifest)
report.logical()
}
pub fn store_physical_size(store : ChunkStore, manifest : Manifest) -> Int {
let report = inspect_storage(store, manifest)
report.physical()
}
pub fn storage_saving_ratio(report : StorageReport) -> Double {
if report.logical() == 0 { 0.0 } else { report.saved().to_double() / report.logical().to_double() }
}
pub fn manifest_has_all_chunks(store : ChunkStore, manifest : Manifest) -> Bool {
collect_missing(store, manifest).length() == 0
}
pub fn manifest_has_no_extra_chunks(store : ChunkStore, manifest : Manifest) -> Bool {
collect_extra(store, manifest).length() == 0
}
pub fn inventory_digest(report : StorageReport) -> String {
digest_string(
report.logical().to_string() + ":" + report.physical().to_string() + ":" + report.chunks().to_string() + ":" + report.unique().to_string(),
)
}
pub fn inventory_equal(left : StorageReport, right : StorageReport) -> Bool {
left.logical() == right.logical() && left.physical() == right.physical() && left.unique() == right.unique()
}
pub fn empty_storage_report() -> StorageReport {
{ logical_bytes: 0, physical_bytes: 0, chunk_count: 0, unique_chunks: 0, deduplicated_bytes: 0, manifest_bytes: 0 }
}
pub fn add_storage_reports(left : StorageReport, right : StorageReport) -> StorageReport {
{ logical_bytes: left.logical() + right.logical(), physical_bytes: left.physical() + right.physical(), chunk_count: left.chunks() + right.chunks(), unique_chunks: left.unique() + right.unique(), deduplicated_bytes: left.saved() + right.saved(), manifest_bytes: left.manifest() + right.manifest() }
}