use crate::backup_reason::Reason;
use crate::chunkid::ChunkId;
use crate::fsentry::FilesystemEntry;
use rusqlite::Connection;
use std::path::Path;
/// An identifier for a file in a generation.
type FileId = i64;
/// A nascent backup generation.
///
/// A nascent generation is one that is being prepared. It isn't
/// finished yet, and it's not actually on the server until the upload
/// of its generation chunk.
pub struct NascentGeneration {
conn: Connection,
fileno: FileId,
}
impl NascentGeneration {
pub fn create
(filename: P) -> anyhow::Result
where
P: AsRef,
{
let conn = sql::create_db(filename.as_ref())?;
Ok(Self { conn, fileno: 0 })
}
pub fn file_count(&self) -> FileId {
self.fileno
}
pub fn insert(
&mut self,
e: FilesystemEntry,
ids: &[ChunkId],
reason: Reason,
) -> anyhow::Result<()> {
let t = self.conn.transaction()?;
self.fileno += 1;
sql::insert_one(&t, e, self.fileno, ids, reason)?;
t.commit()?;
Ok(())
}
pub fn insert_iter<'a>(
&mut self,
entries: impl Iterator, Reason)>>,
) -> anyhow::Result<()> {
let t = self.conn.transaction()?;
for r in entries {
let (e, ids, reason) = r?;
self.fileno += 1;
sql::insert_one(&t, e, self.fileno, &ids[..], reason)?;
}
t.commit()?;
Ok(())
}
}
#[cfg(test)]
mod test {
use super::NascentGeneration;
use tempfile::NamedTempFile;
#[test]
fn empty() {
let filename = NamedTempFile::new().unwrap().path().to_path_buf();
{
let mut _gen = NascentGeneration::create(&filename).unwrap();
// _gen is dropped here; the connection is close; the file
// should not be removed.
}
assert!(filename.exists());
}
}
/// A finished generation.
///
/// A generation is finished when it's on the server. It can be restored.
#[derive(Debug, Clone)]
pub struct FinishedGeneration {
id: ChunkId,
ended: String,
}
impl FinishedGeneration {
pub fn new(id: &str, ended: &str) -> Self {
let id = id.parse().unwrap(); // this never fails
Self {
id,
ended: ended.to_string(),
}
}
pub fn id(&self) -> ChunkId {
self.id.clone()
}
pub fn ended(&self) -> &str {
&self.ended
}
}
/// A local representation of a finished generation.
///
/// This is for querying an existing generation, and other read-only
/// operations.
pub struct LocalGeneration {
conn: Connection,
}
impl LocalGeneration {
pub fn open