diff --git a/src/api2/admin/datastore/backup.rs b/src/api2/admin/datastore/backup.rs index 05332600..db9af1e0 100644 --- a/src/api2/admin/datastore/backup.rs +++ b/src/api2/admin/datastore/backup.rs @@ -261,11 +261,10 @@ fn dynamic_append ( let env: &BackupEnvironment = rpcenv.as_ref(); - let _size = 0; - let _digest = crate::tools::hex_to_digest(digest_str)?; + let digest = crate::tools::hex_to_digest(digest_str)?; + let size = env.lookup_chunk(&digest).ok_or_else(|| format_err!("no such chunk"))?; - // fixme: lookup digest and chunk size, then add - //env.dynamic_writer_append_chunk(wid, size, &digest)?; + env.dynamic_writer_append_chunk(wid, size, &digest)?; env.log(format!("sucessfully added chunk {} to dynamic index {}", digest_str, wid)); diff --git a/src/api2/admin/datastore/backup/environment.rs b/src/api2/admin/datastore/backup/environment.rs index 652f23d3..744a27a0 100644 --- a/src/api2/admin/datastore/backup/environment.rs +++ b/src/api2/admin/datastore/backup/environment.rs @@ -14,6 +14,7 @@ struct SharedBackupState { finished: bool, uid_counter: usize, dynamic_writers: HashMap, + known_chunks: HashMap<[u8;32], u32>, } impl SharedBackupState { @@ -61,6 +62,7 @@ impl BackupEnvironment { finished: false, uid_counter: 0, dynamic_writers: HashMap::new(), + known_chunks: HashMap::new(), }; Self { @@ -76,6 +78,27 @@ impl BackupEnvironment { } } + // Register a Chunk with associated length. A client may only use registered + // chunks (we do not trust clients that far ...) + pub fn register_chunk(&self, digest: [u8; 32], length: u32) -> Result<(), Error> { + let mut state = self.state.lock().unwrap(); + + state.ensure_unfinished()?; + + state.known_chunks.insert(digest, length); + + Ok(()) + } + + pub fn lookup_chunk(&self, digest: &[u8; 32]) -> Option { + let state = self.state.lock().unwrap(); + + match state.known_chunks.get(digest) { + Some(len) => Some(*len), + None => None, + } + } + /// Store the writer with an unique ID pub fn register_dynamic_writer(&self, writer: DynamicIndexWriter) -> Result { let mut state = self.state.lock().unwrap(); @@ -90,7 +113,7 @@ impl BackupEnvironment { } /// Append chunk to dynamic writer - pub fn dynamic_writer_append_chunk(&self, wid: usize, size: u64, digest: &[u8; 32]) -> Result<(), Error> { + pub fn dynamic_writer_append_chunk(&self, wid: usize, size: u32, digest: &[u8; 32]) -> Result<(), Error> { let mut state = self.state.lock().unwrap(); state.ensure_unfinished()?; @@ -100,7 +123,7 @@ impl BackupEnvironment { None => bail!("dynamic writer '{}' not registered", wid), }; - data.0 += size; + data.0 += size as u64; data.1.add_chunk(data.0, digest)?; diff --git a/src/api2/admin/datastore/backup/upload_chunk.rs b/src/api2/admin/datastore/backup/upload_chunk.rs index 075623e3..8e7577fb 100644 --- a/src/api2/admin/datastore/backup/upload_chunk.rs +++ b/src/api2/admin/datastore/backup/upload_chunk.rs @@ -16,22 +16,22 @@ use super::environment::*; pub struct UploadChunk { stream: Body, store: Arc, - size: u64, + size: u32, chunk: Vec, } impl UploadChunk { - pub fn new(stream: Body, store: Arc, size: u64) -> Self { + pub fn new(stream: Body, store: Arc, size: u32) -> Self { Self { stream, store, size, chunk: vec![] } } } impl Future for UploadChunk { - type Item = ([u8; 32], u64); + type Item = ([u8; 32], u32); type Error = failure::Error; - fn poll(&mut self) -> Poll<([u8; 32], u64), failure::Error> { + fn poll(&mut self) -> Poll<([u8; 32], u32), failure::Error> { loop { match try_ready!(self.stream.poll()) { Some(chunk) => { @@ -77,19 +77,20 @@ fn upload_dynamic_chunk( rpcenv: Box, ) -> Result { - let size = tools::required_integer_param(¶m, "size")?; + let size = tools::required_integer_param(¶m, "size")? as u32; let wid = tools::required_integer_param(¶m, "wid")? as usize; let env: &BackupEnvironment = rpcenv.as_ref(); - let upload = UploadChunk::new(req_body, env.datastore.clone(), size as u64); + let upload = UploadChunk::new(req_body, env.datastore.clone(), size); let resp = upload .then(move |result| { let env: &BackupEnvironment = rpcenv.as_ref(); let result = result.and_then(|(digest, size)| { + env.register_chunk(digest, size)?; env.dynamic_writer_append_chunk(wid, size, &digest)?; Ok(json!(tools::digest_to_hex(&digest))) });