[fxfs] Add wrapper around BLOCK_SIZE

This makes log slightly more flexible to use different block sizes and
chunk size as one finds optimal.

Change-Id: If70b6ff302390037dabece44770a3f5007ecf5ed
diff --git a/src/storage/fxfs/src/object_store/log.rs b/src/storage/fxfs/src/object_store/log.rs
index ad7fb84..7cf9f61 100644
--- a/src/storage/fxfs/src/object_store/log.rs
+++ b/src/storage/fxfs/src/object_store/log.rs
@@ -29,9 +29,25 @@
 // TODO: Check all occurrences of unwrap()
 
 pub const BLOCK_SIZE: u64 = 4096; // TODO
-const LOG_FILE_CHUNK_SIZE: u64 = 16 * BLOCK_SIZE; // TODO
+const BLOCKS_PER_FILE_CHUNK: u64 = 16; // TODO
 const RESET_XOR: u64 = 0xffffffffffffffff;
 
+// LogReader and LogWriter expect some properties of log that are same. For not, log might not function properly
+// if they change. This trait defines few such shared properties.
+trait LogProperties {
+    fn block_size(&self) -> u64 {
+        BLOCK_SIZE
+    }
+
+    fn blocks_per_file_chunk(&self) -> u64 {
+        BLOCKS_PER_FILE_CHUNK
+    }
+
+    fn file_chunk_size(&self) -> u64 {
+        self.blocks_per_file_chunk() * self.block_size()
+    }
+}
+
 #[derive(Clone, Debug, Default, Serialize, Deserialize)]
 pub struct LogCheckpoint {
     file_offset: u64,
@@ -217,15 +233,17 @@
     reset: bool,
 }
 
+impl LogProperties for LogWriter {}
+
 impl LogWriter {
     fn new(handle: Option<Box<dyn ObjectHandle>>, last_check_sum: u64) -> LogWriter {
         LogWriter { handle, offset: 0, last_check_sum, buf: Vec::new(), reset: false }
     }
 
     fn pad_to_block(&mut self) -> std::io::Result<()> {
-        let align = self.buf.len() % BLOCK_SIZE as usize;
+        let align = self.buf.len() % self.block_size() as usize;
         if align > 0 {
-            self.write(&vec![0; BLOCK_SIZE as usize - 8 - align])?;
+            self.write(&vec![0; self.block_size() as usize - 8 - align])?;
         }
         Ok(())
     }
@@ -254,7 +272,7 @@
 
 impl std::io::Write for LogWriter {
     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
-        let bs = BLOCK_SIZE as usize;
+        let bs = self.block_size() as usize;
         let mut offset = 0;
         while offset < buf.len() {
             let space = bs - 8 - self.buf.len() % bs;
@@ -278,9 +296,10 @@
     }
 
     fn flush(&mut self) -> std::io::Result<()> {
-        assert!(self.offset % BLOCK_SIZE == 0);
+        assert!(self.offset % self.block_size() == 0);
+        let block_size = self.block_size();
         if let Some(ref mut handle) = self.handle {
-            let bs = BLOCK_SIZE as usize;
+            let bs = block_size as usize;
             // TODO: Zero copy/move.
             let len = self.buf.len() - self.buf.len() % bs;
             if len > 0 {
@@ -296,6 +315,8 @@
 
 pub struct Log(Mutex<Option<InitializedLog>>);
 
+impl LogProperties for Log {}
+
 impl Log {
     pub fn new() -> Log {
         Log(Mutex::new(None))
@@ -481,7 +502,7 @@
         self.commit(transaction);
         println!("log object id {:?}", log_handle.object_id());
         let mut transaction = Transaction::new();
-        log_handle.preallocate_range(0..LOG_FILE_CHUNK_SIZE, &mut transaction).unwrap(); // TODO
+        log_handle.preallocate_range(0..self.file_chunk_size(), &mut transaction).unwrap(); // TODO
         self.commit(transaction);
 
         // Fill in the missing details.
@@ -558,25 +579,28 @@
     log_file_checkpoints: HashMap<u64, LogCheckpoint>,
 }
 
+impl LogProperties for InitializedLog {}
+
 impl InitializedLog {
     fn maybe_extend_log_file(&mut self, writer: Option<&mut LogWriter>) {
+        let file_chunk_size = self.file_chunk_size();
         let (writer, second_writer) = match writer {
             None => (&mut self.writer, None),
             Some(writer) => (writer, Some(&mut self.writer)),
         };
-        // TODO: what if it needs to grow by more than LOG_FILE_CHUNK_SIZE?
+        // TODO: what if it needs to grow by more than file_chunk_size()?
         let file_offset = writer.log_file_checkpoint().file_offset;
         let handle = match writer.handle {
             None => return,
             Some(ref mut handle) => handle,
         };
         let size = handle.get_size();
-        if file_offset + LOG_FILE_CHUNK_SIZE <= size {
+        if file_offset + file_chunk_size <= size {
             return;
         }
         let mut transaction = Transaction::new();
         let allocated =
-            handle.preallocate_range(size..size + LOG_FILE_CHUNK_SIZE, &mut transaction).unwrap(); // TODO
+            handle.preallocate_range(size..size + file_chunk_size, &mut transaction).unwrap(); // TODO
         let object_id = handle.object_id();
         let log_file_checkpoint = second_writer.unwrap_or(writer).write_transaction(&transaction);
 
@@ -586,7 +610,7 @@
         assert!(writer.log_file_checkpoint().file_offset <= size);
         let file_offset = writer.log_file_checkpoint().file_offset;
         let handle = writer.handle.as_ref().unwrap();
-        assert!(file_offset + LOG_FILE_CHUNK_SIZE <= handle.get_size());
+        assert!(file_offset + file_chunk_size <= handle.get_size());
         if object_id == SUPER_BLOCK_OBJECT_ID {
             for dev_range in allocated.iter() {
                 let extent = Extent {
@@ -798,6 +822,8 @@
     }
 }
 
+impl LogProperties for LogReader {}
+
 struct LogReader {
     handle: Box<dyn LogReaderHandle>,
     buf_offset: usize,
@@ -827,9 +853,9 @@
         if self.buf_offset + 8 >= self.buf.len() {
             LogCheckpoint::new(self.read_offset, self.last_check_sum)
         } else {
-            assert!(self.read_offset % BLOCK_SIZE == 0);
+            assert!(self.read_offset % self.block_size() == 0);
             LogCheckpoint::new(
-                self.read_offset - BLOCK_SIZE + self.buf_offset as u64,
+                self.read_offset - self.block_size() + self.buf_offset as u64,
                 self.last_check_sum,
             )
         }
@@ -851,16 +877,16 @@
 impl std::io::Read for LogReader {
     fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
         // println!("log reading {:?} @ {:?}", buf.len(), self.buf_offset);
-        assert!(buf.len() < BLOCK_SIZE as usize - 8); // TODO
+        assert!(buf.len() < self.block_size() as usize - 8); // TODO
         let mut offset = 0;
-        let bs = BLOCK_SIZE as usize;
+        let bs = self.block_size() as usize;
         // TODO: Fix this to read more than one block maybe?
         while offset < buf.len() {
             if self.buf_offset + 8 >= self.buf.len() {
                 if self.bad_check_sum {
                     return Ok(offset);
                 }
-                let align = self.read_offset % BLOCK_SIZE;
+                let align = self.read_offset % self.block_size();
                 self.buf.resize(bs, 0);
                 self.handle.read(self.read_offset - align, &mut self.buf)?;
                 let end = bs - 8;
@@ -875,12 +901,12 @@
                         // block.
                         self.found_reset = true;
                         self.last_read_check_sum = stored_check_sum;
-                        self.read_offset += BLOCK_SIZE - align;
+                        self.read_offset += self.block_size() - align;
                     }
                     return Ok(offset);
                 } else {
                     self.last_read_check_sum = stored_check_sum;
-                    self.read_offset += BLOCK_SIZE - align;
+                    self.read_offset += self.block_size() - align;
                     self.buf_offset = align as usize;
                 }
             }