Implementation of insert.
authorGreg Burri <greg.burri@gmail.com>
Sun, 18 Sep 2022 20:29:29 +0000 (22:29 +0200)
committerGreg Burri <greg.burri@gmail.com>
Sun, 18 Sep 2022 20:29:29 +0000 (22:29 +0200)
ch7-file-and-storage/actionkv/src/akv_mem.rs
ch7-file-and-storage/actionkv/src/lib.rs

index 87d3c0c..2343094 100644 (file)
@@ -23,8 +23,8 @@ fn main() {
     let args: Vec<String> = std::env::args().collect();
     let fname = args.get(1).expect(&USAGE);
 
-    let action: &str = args.get(2).expect(&USAGE).as_ref();
-    let key: &str = args.get(3).expect(&USAGE).as_ref();
+    let action = args.get(2).expect(&USAGE).as_ref();
+    let key = args.get(3).expect(&USAGE).as_ref();
     let maybe_value = args.get(4);
 
     let path = std::path::Path::new(&fname);
@@ -40,11 +40,12 @@ fn main() {
         },
 
         "delete" => store.delete(key).unwrap(),
-
+        */
         "insert" => {
             let value = maybe_value.expect(&USAGE).as_ref();
             store.insert(key, value).unwrap();
         },
+        /*
 
         "update" => {
             let value = maybe_value.expect(&USAGE).as_ref();
index c626a82..e56409f 100644 (file)
@@ -1,9 +1,16 @@
-use std::io::{self, BufReader, Seek, SeekFrom, Read};
-use byteorder::{LittleEndian, ReadBytesExt};
+use std::{
+    collections::HashMap,
+    fs::{File, OpenOptions},
+    io::{self, prelude::*, BufReader, BufWriter, SeekFrom},
+    path::Path,
+};
+
+use byteorder::{
+    LittleEndian,
+    ReadBytesExt, // Extend 'Read' trait with some methods.
+    WriteBytesExt,
+};
 use crc::Crc;
-use std::fs::{File, OpenOptions};
-use std::path::Path;
-use std::collections::HashMap;
 use serde_derive::{Serialize, Deserialize};
 
 type ByteString = Vec<u8>;
@@ -22,30 +29,10 @@ pub struct ActionKV {
 }
 
 impl ActionKV {
-    fn process_record<R: Read>(f: &mut R) -> io::Result<KeyValuePair> {
-        let saved_checksum = f.read_u32::<LittleEndian>()?;
-        let key_len = f.read_u32::<LittleEndian>()?;
-        let val_len = f.read_u32::<LittleEndian>()?;
-        let data_len = key_len + val_len;
-
-        let mut data = ByteString::with_capacity(data_len as usize);
-
-        {
-            f.by_ref().take(data_len as u64).read_to_end(&mut data)?;
-        }
-
-        debug_assert_eq!(data.len(), data_len as usize);
-
-        let crc = Crc::<u32>::new(&crc::CRC_32_CKSUM);
-        let checksum = crc.checksum(&data);
-        if checksum != saved_checksum {
-            panic!("data corruption encountered ({:08x} != {:08x})", checksum, saved_checksum);
-        }
-
-        let value = data.split_off(key_len as usize);
-        let key = data;
-
-        Ok(KeyValuePair { key, value })
+    pub fn insert(&mut self, key: &ByteStr, value: &ByteStr) -> io::Result<()> {
+        let position = self.write_to_file(key, value)?;
+        self.index.insert(key.to_vec(), position);
+        Ok(())
     }
 
     pub fn open(path: &Path) -> io::Result<Self> {
@@ -77,4 +64,60 @@ impl ActionKV {
 
         Ok(())
     }
+
+    ///// Private methods /////
+
+    fn write_to_file(&mut self, key: &ByteStr, value: &ByteStr) -> io::Result<u64> {
+        let mut f = BufWriter::new(&mut self.f);
+        let key_len = key.len();
+        let val_len = value.len();
+        let mut tmp = ByteString::with_capacity(key_len + val_len);
+
+        for byte in key {
+            tmp.push(*byte);
+        }
+
+        for byte in value {
+            tmp.push(*byte);
+        }
+
+        let crc = Crc::<u32>::new(&crc::CRC_32_CKSUM);
+        let checksum = crc.checksum(&tmp);
+
+        let next_byte = SeekFrom::End(0);
+        let current_position = f.seek(SeekFrom::Current(0))?;
+
+        f.seek(next_byte)?; // TODO: Is it necessary?
+        f.write_u32::<LittleEndian>(checksum)?;
+        f.write_u32::<LittleEndian>(key_len as u32)?;
+        f.write_u32::<LittleEndian>(val_len as u32)?;
+        f.write_all(&mut tmp)?;
+
+        Ok(current_position)
+    }
+
+    /// Read the next record from the given reader (from the current reader position).
+    fn process_record<R: Read>(f: &mut R) -> io::Result<KeyValuePair> {
+        let saved_checksum = f.read_u32::<LittleEndian>()?;
+        let key_len = f.read_u32::<LittleEndian>()?;
+        let val_len = f.read_u32::<LittleEndian>()?;
+        let data_len = key_len + val_len;
+
+        let mut data = ByteString::with_capacity(data_len as usize);
+
+        f.take(data_len as u64).read_to_end(&mut data)?;
+
+        debug_assert_eq!(data.len(), data_len as usize);
+
+        let crc = Crc::<u32>::new(&crc::CRC_32_CKSUM);
+        let checksum = crc.checksum(&data);
+        if checksum != saved_checksum {
+            panic!("data corruption encountered ({:08x} != {:08x})", checksum, saved_checksum);
+        }
+
+        let value = data.split_off(key_len as usize);
+        let key = data;
+
+        Ok(KeyValuePair { key, value })
+    }
 }
\ No newline at end of file