From 59c06d79534d4029c87e92bafa0e3c5a652dc0da Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Sun, 18 Sep 2022 22:29:29 +0200 Subject: [PATCH] Implementation of insert. --- ch7-file-and-storage/actionkv/src/akv_mem.rs | 7 +- ch7-file-and-storage/actionkv/src/lib.rs | 101 +++++++++++++------ 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/ch7-file-and-storage/actionkv/src/akv_mem.rs b/ch7-file-and-storage/actionkv/src/akv_mem.rs index 87d3c0c..2343094 100644 --- a/ch7-file-and-storage/actionkv/src/akv_mem.rs +++ b/ch7-file-and-storage/actionkv/src/akv_mem.rs @@ -23,8 +23,8 @@ fn main() { let args: Vec = 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(); diff --git a/ch7-file-and-storage/actionkv/src/lib.rs b/ch7-file-and-storage/actionkv/src/lib.rs index c626a82..e56409f 100644 --- a/ch7-file-and-storage/actionkv/src/lib.rs +++ b/ch7-file-and-storage/actionkv/src/lib.rs @@ -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; @@ -22,30 +29,10 @@ pub struct ActionKV { } impl ActionKV { - fn process_record(f: &mut R) -> io::Result { - let saved_checksum = f.read_u32::()?; - let key_len = f.read_u32::()?; - let val_len = f.read_u32::()?; - 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::::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 { @@ -77,4 +64,60 @@ impl ActionKV { Ok(()) } + + ///// Private methods ///// + + fn write_to_file(&mut self, key: &ByteStr, value: &ByteStr) -> io::Result { + 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::::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::(checksum)?; + f.write_u32::(key_len as u32)?; + f.write_u32::(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(f: &mut R) -> io::Result { + let saved_checksum = f.read_u32::()?; + let key_len = f.read_u32::()?; + let val_len = f.read_u32::()?; + 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::::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 -- 2.45.2