From 5cf780ab9817ed829a6fe7afe83e8bc3cee431c7 Mon Sep 17 00:00:00 2001
From: Yeastplume <yeastplume@gmail.com>
Date: Fri, 9 Mar 2018 17:17:48 +0000
Subject: [PATCH] Rm log rewind on startup (#760)

* add rewind to block height to rm_log on startup

* add rewind to block height to rm_log on startup

* flush remove log
---
 chain/src/chain.rs | 10 +++++++++-
 store/src/pmmr.rs  | 18 ++++++++++++++----
 store/src/types.rs | 12 +++++++++---
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/chain/src/chain.rs b/chain/src/chain.rs
index 55e2da9af..93e71929d 100644
--- a/chain/src/chain.rs
+++ b/chain/src/chain.rs
@@ -157,7 +157,15 @@ impl Chain {
 		// check if we have a head in store, otherwise the genesis block is it
 		let head = store.head();
 		let txhashset_md = match head {
-			Ok(h) => Some(store.get_block_pmmr_file_metadata(&h.last_block_h)?),
+			Ok(h) => {
+				// Add the height to the metadata for the use of the rewind log, as this isn't
+				// stored
+				let mut ts = store.get_block_pmmr_file_metadata(&h.last_block_h)?;
+				ts.output_file_md.block_height = h.height;
+				ts.rproof_file_md.block_height = h.height;
+				ts.kernel_file_md.block_height = h.height;
+				Some(ts)
+			}
 			Err(NotFoundErr) => None,
 			Err(e) => return Err(Error::StoreErr(e, "chain init load head".to_owned())),
 		};
diff --git a/store/src/pmmr.rs b/store/src/pmmr.rs
index 373750395..4aa672ffd 100644
--- a/store/src/pmmr.rs
+++ b/store/src/pmmr.rs
@@ -35,6 +35,8 @@ pub const RM_LOG_MAX_NODES: usize = 10000;
 /// stored
 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
 pub struct PMMRFileMetadata {
+	/// The block height represented by these indices in the file
+	pub block_height: u64,
 	/// last written index of the hash file
 	pub last_hash_file_pos: u64,
 	/// last written index of the data file
@@ -43,6 +45,7 @@ pub struct PMMRFileMetadata {
 
 impl Writeable for PMMRFileMetadata {
 	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
+		writer.write_u64(self.block_height)?;
 		writer.write_u64(self.last_hash_file_pos)?;
 		writer.write_u64(self.last_data_file_pos)?;
 		Ok(())
@@ -52,6 +55,7 @@ impl Writeable for PMMRFileMetadata {
 impl Readable for PMMRFileMetadata {
 	fn read(reader: &mut Reader) -> Result<PMMRFileMetadata, ser::Error> {
 		Ok(PMMRFileMetadata {
+			block_height: reader.read_u64()?,
 			last_hash_file_pos: reader.read_u64()?,
 			last_data_file_pos: reader.read_u64()?,
 		})
@@ -62,6 +66,7 @@ impl PMMRFileMetadata {
 	/// Return fields with all positions = 0
 	pub fn empty() -> PMMRFileMetadata {
 		PMMRFileMetadata {
+			block_height: 0,
 			last_hash_file_pos: 0,
 			last_data_file_pos: 0,
 		}
@@ -211,13 +216,17 @@ where
 	/// Instantiates a new PMMR backend that will use the provided directly to
 	/// store its files.
 	pub fn new(data_dir: String, file_md: Option<PMMRFileMetadata>) -> io::Result<PMMRBackend<T>> {
-		let (hash_to_pos, data_to_pos) = match file_md {
-			Some(m) => (m.last_hash_file_pos, m.last_data_file_pos),
-			None => (0, 0),
+		let (height, hash_to_pos, data_to_pos) = match file_md {
+			Some(m) => (
+				m.block_height as u32,
+				m.last_hash_file_pos,
+				m.last_data_file_pos,
+			),
+			None => (0, 0, 0),
 		};
 		let hash_file =
 			AppendOnlyFile::open(format!("{}/{}", data_dir, PMMR_HASH_FILE), hash_to_pos)?;
-		let rm_log = RemoveLog::open(format!("{}/{}", data_dir, PMMR_RM_LOG_FILE))?;
+		let rm_log = RemoveLog::open(format!("{}/{}", data_dir, PMMR_RM_LOG_FILE), height)?;
 		let prune_list = read_ordered_vec(format!("{}/{}", data_dir, PMMR_PRUNED_FILE), 8)?;
 		let data_file =
 			AppendOnlyFile::open(format!("{}/{}", data_dir, PMMR_DATA_FILE), data_to_pos)?;
@@ -290,6 +299,7 @@ where
 	/// Return last written buffer positions for the hash file and the data file
 	pub fn last_file_positions(&self) -> PMMRFileMetadata {
 		PMMRFileMetadata {
+			block_height: 0,
 			last_hash_file_pos: self.hash_file.last_buffer_pos() as u64,
 			last_data_file_pos: self.data_file.last_buffer_pos() as u64,
 		}
diff --git a/store/src/types.rs b/store/src/types.rs
index 74b2a2c32..8419353d7 100644
--- a/store/src/types.rs
+++ b/store/src/types.rs
@@ -28,6 +28,7 @@ use libc::{ftruncate as ftruncate64, off_t as off64_t};
 
 use core::ser;
 
+/// Noop
 pub fn prune_noop(_pruned_data: &[u8]) {}
 
 /// Wrapper for a file that can be read at any position (random read) but for
@@ -229,14 +230,19 @@ pub struct RemoveLog {
 impl RemoveLog {
 	/// Open the remove log file. The content of the file will be read in memory
 	/// for fast checking.
-	pub fn open(path: String) -> io::Result<RemoveLog> {
+	pub fn open(path: String, rewind_to_index: u32) -> io::Result<RemoveLog> {
 		let removed = read_ordered_vec(path.clone(), 12)?;
-		Ok(RemoveLog {
+		let mut rl = RemoveLog {
 			path: path,
 			removed: removed,
 			removed_tmp: vec![],
 			removed_bak: vec![],
-		})
+		};
+		if rewind_to_index > 0 {
+			rl.rewind(rewind_to_index)?;
+			rl.flush()?;
+		}
+		Ok(rl)
 	}
 
 	/// Truncate and empties the remove log.