From b893a6c8ee0027981642e0c5152b18d6417ced30 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Tue, 28 Nov 2017 18:43:02 -0500 Subject: [PATCH] Back up the removed log before truncating in memory Without a backup, the in-memory data structure stays truncated even if the rewind is abandoned. Also add some logging on our most problematic block in case it still is problematic. --- chain/src/sumtree.rs | 6 +++++- store/src/sumtree.rs | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/chain/src/sumtree.rs b/chain/src/sumtree.rs index 1db758c59..090887797 100644 --- a/chain/src/sumtree.rs +++ b/chain/src/sumtree.rs @@ -239,9 +239,13 @@ impl<'a> Extension<'a> { pub fn apply_block(&mut self, b: &Block) -> Result<(), Error> { // doing inputs first guarantees an input can't spend an output in the - // same block, enforcing block cut-through + // same block, enforcing block cut-through for input in &b.inputs { let pos_res = self.commit_index.get_output_pos(&input.commitment()); + if b.hash().to_string() == "f697a877" { + debug!(LOGGER, "input pos: {:?}, commit: {} {:?}", + pos_res, input.commitment().hash(), input.commitment()); + } if let Ok(pos) = pos_res { match self.output_pmmr.prune(pos, b.header.height as u32) { Ok(true) => { diff --git a/store/src/sumtree.rs b/store/src/sumtree.rs index 17454da7c..7d57bbd49 100644 --- a/store/src/sumtree.rs +++ b/store/src/sumtree.rs @@ -163,6 +163,8 @@ struct RemoveLog { removed: Vec<(u64, u32)>, // Holds positions temporarily until flush is called. removed_tmp: Vec<(u64, u32)>, + // Holds truncated removed temporarily until discarded or committed + removed_bak: Vec<(u64, u32)>, } impl RemoveLog { @@ -174,6 +176,7 @@ impl RemoveLog { path: path, removed: removed, removed_tmp: vec![], + removed_bak: vec![], }) } @@ -181,10 +184,14 @@ impl RemoveLog { fn truncate(&mut self, last_offs: u32) -> io::Result<()> { // simplifying assumption: we always remove older than what's in tmp self.removed_tmp = vec![]; + // DEBUG + let _ = self.flush_truncate(last_offs); if last_offs == 0 { self.removed = vec![]; } else { + // backing it up before truncating + self.removed_bak = self.removed.clone(); self.removed = self.removed .iter() .filter(|&&(_, idx)| idx < last_offs) @@ -194,6 +201,15 @@ impl RemoveLog { Ok(()) } + // DEBUG: saves the remove log to the side before each truncate + fn flush_truncate(&mut self, last_offs: u32) -> io::Result<()> { + let mut file = File::create(format!("{}.{}", self.path.clone(), last_offs))?; + for elmt in &self.removed { + file.write_all(&ser::ser_vec(&elmt).unwrap()[..])?; + } + file.sync_data() + } + /// Append a set of new positions to the remove log. Both adds those /// positions the ordered in-memory set and to the file. fn append(&mut self, elmts: Vec, index: u32) -> io::Result<()> { @@ -223,11 +239,16 @@ impl RemoveLog { file.write_all(&ser::ser_vec(&elmt).unwrap()[..])?; } self.removed_tmp = vec![]; + self.removed_bak = vec![]; file.sync_data() } /// Discard pending changes fn discard(&mut self) { + if self.removed_bak.len() > 0 { + self.removed = self.removed_bak.clone(); + self.removed_bak = vec![]; + } self.removed_tmp = vec![]; }