1use crate::manifest::{BackupManifest, FileEntry};
2use powdb_storage::catalog::Catalog;
3use std::io;
4use std::path::Path;
5use std::time::{SystemTime, UNIX_EPOCH};
6
7pub fn full_backup(catalog: &mut Catalog, dest: &Path) -> io::Result<BackupManifest> {
14 catalog.checkpoint()?;
15 let source_lsn = catalog.max_lsn();
16 let src = catalog.data_dir().to_path_buf();
17 std::fs::create_dir_all(dest)?;
18
19 let mut files = Vec::new();
20 for entry in std::fs::read_dir(&src)? {
21 let entry = entry?;
22 let name = entry.file_name().to_string_lossy().to_string();
23 let is_durable = name == "catalog.bin" || name.ends_with(".heap") || name.ends_with(".idx");
26 if !is_durable {
27 continue;
28 }
29 let bytes = std::fs::read(entry.path())?;
30 let hash = blake3::hash(&bytes).to_hex().to_string();
31 std::fs::write(dest.join(&name), &bytes)?;
32 files.push(FileEntry {
33 name,
34 len: bytes.len() as u64,
35 blake3_hex: hash,
36 });
37 }
38 files.sort_by(|a, b| a.name.cmp(&b.name));
39
40 let manifest = BackupManifest {
41 format_version: BackupManifest::FORMAT_VERSION,
42 created_unix_secs: SystemTime::now()
43 .duration_since(UNIX_EPOCH)
44 .map(|d| d.as_secs())
45 .unwrap_or(0),
46 source_lsn,
47 files,
48 };
49 manifest.write(dest)?;
50 Ok(manifest)
51}