diff options
author | Lars Wirzenius <liw@liw.fi> | 2020-12-31 09:35:08 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2020-12-31 10:25:30 +0200 |
commit | b672b2cdcb194f6fda77bdb76aa7b01a1eed0b2e (patch) | |
tree | 24a29e9b3b99f7f039f4ad7ecd299711337172f7 /src/generation.rs | |
parent | f3810e171fed0d3d7eca159024dea2b31427b7ff (diff) | |
download | obnam2-b672b2cdcb194f6fda77bdb76aa7b01a1eed0b2e.tar.gz |
refactor: add LocalGeneration type for read-only operations
This splits the use of NascentGeneration to more cohesive "new
generation being built" versus "existing generation being restored".
Diffstat (limited to 'src/generation.rs')
-rw-r--r-- | src/generation.rs | 114 |
1 files changed, 59 insertions, 55 deletions
diff --git a/src/generation.rs b/src/generation.rs index 5d04a9f..4e7589c 100644 --- a/src/generation.rs +++ b/src/generation.rs @@ -6,8 +6,8 @@ use std::path::Path; /// 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, yet, or not -/// completely. It can't be restored. +/// finished yet, and it's not actually on the server until the upload +/// of its generation chunk. pub struct NascentGeneration { conn: Connection, fileno: u64, @@ -32,16 +32,8 @@ impl NascentGeneration { Ok(Self { conn, fileno: 0 }) } - pub fn open<P>(filename: P) -> anyhow::Result<Self> - where - P: AsRef<Path>, - { - let flags = OpenFlags::SQLITE_OPEN_READ_WRITE; - let conn = Connection::open_with_flags(filename, flags)?; - conn.pragma_update(None, "journal_mode", &"WAL")?; - let fileno = find_max_fileno(&conn)?; - - Ok(Self { conn, fileno }) + pub fn file_count(&self) -> u64 { + self.fileno } pub fn insert(&mut self, e: FilesystemEntry, ids: &[ChunkId]) -> anyhow::Result<()> { @@ -65,36 +57,6 @@ impl NascentGeneration { t.commit()?; Ok(()) } - - pub fn file_count(&self) -> u64 { - self.fileno - } - - pub fn files(&self) -> anyhow::Result<Vec<(u64, FilesystemEntry)>> { - let mut stmt = self.conn.prepare("SELECT * FROM files")?; - let iter = stmt.query_map(params![], |row| row_to_entry(row))?; - let mut files: Vec<(u64, FilesystemEntry)> = vec![]; - for x in iter { - let (fileno, json) = x?; - let entry = serde_json::from_str(&json)?; - files.push((fileno, entry)); - } - Ok(files) - } - - pub fn chunkids(&self, fileno: u64) -> anyhow::Result<Vec<ChunkId>> { - let fileno = fileno as i64; - let mut stmt = self - .conn - .prepare("SELECT chunkid FROM chunks WHERE fileno = ?1")?; - let iter = stmt.query_map(params![fileno], |row| Ok(row.get(0)?))?; - let mut ids: Vec<ChunkId> = vec![]; - for x in iter { - let fileno: String = x?; - ids.push(ChunkId::from(&fileno)); - } - Ok(ids) - } } fn row_to_entry(row: &Row) -> rusqlite::Result<(u64, String)> { @@ -125,19 +87,6 @@ fn insert_one( Ok(()) } -fn find_max_fileno(conn: &Connection) -> anyhow::Result<u64> { - let mut stmt = conn.prepare("SELECT fileno FROM files ORDER BY fileno")?; - let mut rows = stmt.query(params![])?; - let mut fileno: i64 = 0; - while let Some(row) = rows.next()? { - let x = row.get(0)?; - if x > fileno { - fileno = x; - } - } - Ok(fileno as u64) -} - #[cfg(test)] mod test { use super::NascentGeneration; @@ -181,3 +130,58 @@ impl FinishedGeneration { &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<P>(filename: P) -> anyhow::Result<Self> + where + P: AsRef<Path>, + { + let flags = OpenFlags::SQLITE_OPEN_READ_WRITE; + let conn = Connection::open_with_flags(filename, flags)?; + conn.pragma_update(None, "journal_mode", &"WAL")?; + + Ok(Self { conn }) + } + + pub fn file_count(&self) -> anyhow::Result<u32> { + let mut stmt = self.conn.prepare("SELECT count(*) FROM files")?; + let mut iter = stmt.query_map(params![], |row| row.get(0))?; + let count = iter.next().expect("SQL count result"); + let count = count?; + Ok(count) + } + + pub fn files(&self) -> anyhow::Result<Vec<(u64, FilesystemEntry)>> { + let mut stmt = self.conn.prepare("SELECT * FROM files")?; + let iter = stmt.query_map(params![], |row| row_to_entry(row))?; + let mut files: Vec<(u64, FilesystemEntry)> = vec![]; + for x in iter { + let (fileno, json) = x?; + let entry = serde_json::from_str(&json)?; + files.push((fileno, entry)); + } + Ok(files) + } + + pub fn chunkids(&self, fileno: u64) -> anyhow::Result<Vec<ChunkId>> { + let fileno = fileno as i64; + let mut stmt = self + .conn + .prepare("SELECT chunkid FROM chunks WHERE fileno = ?1")?; + let iter = stmt.query_map(params![fileno], |row| Ok(row.get(0)?))?; + let mut ids: Vec<ChunkId> = vec![]; + for x in iter { + let fileno: String = x?; + ids.push(ChunkId::from(&fileno)); + } + Ok(ids) + } +} |