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.
This commit is contained in:
Ignotus Peverell 2017-11-28 18:43:02 -05:00 committed by Simon B
parent 6b48e7840d
commit b893a6c8ee
2 changed files with 26 additions and 1 deletions

View file

@ -242,6 +242,10 @@ impl<'a> Extension<'a> {
// same block, enforcing block cut-through // same block, enforcing block cut-through
for input in &b.inputs { for input in &b.inputs {
let pos_res = self.commit_index.get_output_pos(&input.commitment()); 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 { if let Ok(pos) = pos_res {
match self.output_pmmr.prune(pos, b.header.height as u32) { match self.output_pmmr.prune(pos, b.header.height as u32) {
Ok(true) => { Ok(true) => {

View file

@ -163,6 +163,8 @@ struct RemoveLog {
removed: Vec<(u64, u32)>, removed: Vec<(u64, u32)>,
// Holds positions temporarily until flush is called. // Holds positions temporarily until flush is called.
removed_tmp: Vec<(u64, u32)>, removed_tmp: Vec<(u64, u32)>,
// Holds truncated removed temporarily until discarded or committed
removed_bak: Vec<(u64, u32)>,
} }
impl RemoveLog { impl RemoveLog {
@ -174,6 +176,7 @@ impl RemoveLog {
path: path, path: path,
removed: removed, removed: removed,
removed_tmp: vec![], removed_tmp: vec![],
removed_bak: vec![],
}) })
} }
@ -181,10 +184,14 @@ impl RemoveLog {
fn truncate(&mut self, last_offs: u32) -> io::Result<()> { fn truncate(&mut self, last_offs: u32) -> io::Result<()> {
// simplifying assumption: we always remove older than what's in tmp // simplifying assumption: we always remove older than what's in tmp
self.removed_tmp = vec![]; self.removed_tmp = vec![];
// DEBUG
let _ = self.flush_truncate(last_offs);
if last_offs == 0 { if last_offs == 0 {
self.removed = vec![]; self.removed = vec![];
} else { } else {
// backing it up before truncating
self.removed_bak = self.removed.clone();
self.removed = self.removed self.removed = self.removed
.iter() .iter()
.filter(|&&(_, idx)| idx < last_offs) .filter(|&&(_, idx)| idx < last_offs)
@ -194,6 +201,15 @@ impl RemoveLog {
Ok(()) 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 /// Append a set of new positions to the remove log. Both adds those
/// positions the ordered in-memory set and to the file. /// positions the ordered in-memory set and to the file.
fn append(&mut self, elmts: Vec<u64>, index: u32) -> io::Result<()> { fn append(&mut self, elmts: Vec<u64>, index: u32) -> io::Result<()> {
@ -223,11 +239,16 @@ impl RemoveLog {
file.write_all(&ser::ser_vec(&elmt).unwrap()[..])?; file.write_all(&ser::ser_vec(&elmt).unwrap()[..])?;
} }
self.removed_tmp = vec![]; self.removed_tmp = vec![];
self.removed_bak = vec![];
file.sync_data() file.sync_data()
} }
/// Discard pending changes /// Discard pending changes
fn discard(&mut self) { fn discard(&mut self) {
if self.removed_bak.len() > 0 {
self.removed = self.removed_bak.clone();
self.removed_bak = vec![];
}
self.removed_tmp = vec![]; self.removed_tmp = vec![];
} }