diff options
-rw-r--r-- | src/bin/obnam-server.rs | 2 | ||||
-rw-r--r-- | src/index.rs | 15 | ||||
-rw-r--r-- | src/indexedstore.rs | 28 |
3 files changed, 44 insertions, 1 deletions
diff --git a/src/bin/obnam-server.rs b/src/bin/obnam-server.rs index 19f2e99..0e9d4e6 100644 --- a/src/bin/obnam-server.rs +++ b/src/bin/obnam-server.rs @@ -188,6 +188,8 @@ pub async fn search_chunks( } if key == "generation" && value == "true" { store.find_generations().expect("SQL lookup failed") + } else if key == "data" && value == "true" { + store.find_file_chunks().expect("SQL lookup failed") } else if key == "sha256" { store.find_by_sha256(value).expect("SQL lookup failed") } else { diff --git a/src/index.rs b/src/index.rs index f7300da..9386e73 100644 --- a/src/index.rs +++ b/src/index.rs @@ -75,6 +75,10 @@ impl Index { pub fn find_generations(&self) -> IndexResult<Vec<ChunkId>> { sql::find_generations(&self.conn) } + + pub fn all_chunks(&self) -> IndexResult<Vec<ChunkId>> { + sql::find_chunk_ids(&self.conn) + } } #[cfg(test)] @@ -243,6 +247,17 @@ mod sql { Ok(ids) } + pub fn find_chunk_ids(conn: &Connection) -> IndexResult<Vec<ChunkId>> { + let mut stmt = conn.prepare("SELECT id FROM chunks WHERE generation IS 0")?; + let iter = stmt.query_map(params![], |row| row_to_id(row))?; + let mut ids = vec![]; + for x in iter { + let x = x?; + ids.push(x); + } + Ok(ids) + } + fn row_to_meta(row: &Row) -> rusqlite::Result<ChunkMeta> { let sha256: String = row.get(row.column_index("sha256")?)?; let generation: i32 = row.get(row.column_index("generation")?)?; diff --git a/src/indexedstore.rs b/src/indexedstore.rs index 3f347dd..f2d1831 100644 --- a/src/indexedstore.rs +++ b/src/indexedstore.rs @@ -1,8 +1,9 @@ -use crate::chunk::DataChunk; +use crate::chunk::{DataChunk, GenerationChunk, GenerationChunkError}; use crate::chunkid::ChunkId; use crate::chunkmeta::ChunkMeta; use crate::index::{Index, IndexError}; use crate::store::{Store, StoreError}; +use std::collections::HashSet; use std::path::Path; /// A store for chunks and their metadata. @@ -21,6 +22,9 @@ pub enum IndexedError { #[error(transparent)] IndexError(#[from] IndexError), + #[error(transparent)] + GenerationChunkError(#[from] GenerationChunkError), + /// An error from Store. #[error(transparent)] SqlError(#[from] StoreError), @@ -64,6 +68,28 @@ impl IndexedStore { Ok(self.index.find_generations()?) } + pub fn find_file_chunks(&self) -> IndexedResult<Vec<ChunkId>> { + let gen_ids = self.find_generations()?; + + let mut sql_chunks: HashSet<ChunkId> = HashSet::new(); + for id in gen_ids { + let gen_chunk = self.store.load(&id)?; + let gen = GenerationChunk::from_data_chunk(&gen_chunk)?; + for sqlite_chunk_id in gen.chunk_ids() { + sql_chunks.insert(sqlite_chunk_id.clone()); + } + } + + let all_chunk_ids = self.index.all_chunks()?; + let file_chunks = all_chunk_ids + .iter() + .filter(|id| !sql_chunks.contains(id)) + .map(|id| id.clone()) + .collect(); + + Ok(file_chunks) + } + pub fn remove(&mut self, id: &ChunkId) -> IndexedResult<()> { self.index.remove_meta(id)?; self.store.delete(id)?; |