环境
- Time 2022-12-13
- WSL-Ubuntu 22.04
- Rust 1.65.0
前言
说明
参考:https://github.com/pingcap/talent-plan
目标
在上一节的基础上,根据提供的索引,到文件中读取命令和值。
Cargo.toml
[package]
edition = "2021"
name = "kvs"
version = "1.0.0"[dependencies]
clap = {version = "4", features = ["derive"]}
serde = {version = "1", features = ["derive"]}
serde_json = "1"
log.rs
use std::collections::BTreeMap;use crate::cmd::{Command, CommandPosition};use self::{reader::PosBufReader, writer::PosBufWriter};mod reader;
mod writer;pub struct CommandLog {reader: PosBufReader,writer: PosBufWriter,index: BTreeMap<String, CommandPosition>,
}pub type KvResult = anyhow::Result<Option<String>>;impl CommandLog {pub fn new() -> anyhow::Result<Self> {let path = "/root/log/1.log";let writer = PosBufWriter::new(path)?;let mut index = BTreeMap::default();let mut reader = PosBufReader::new(path)?;reader.load(&mut index)?;Ok(Self {reader,writer,index,})}pub fn get(&mut self, key: &str) -> KvResult {self.reader.read(self.index.get(key))}pub fn set(&mut self, key: String, value: String) -> KvResult {let result = self.reader.read(self.index.get(&key));let command = Command::Set {key: key.to_string(),value,};let json = serde_json::to_string(&command)?;let position = self.writer.write(json.as_bytes())?;self.index.insert(key, position);result}pub fn remove(&mut self, key: String) -> KvResult {let result = self.reader.read(self.index.get(&key));let command = Command::Remove {key: key.to_string(),};let json = serde_json::to_string(&command)?;self.writer.write(json.as_bytes())?;self.index.remove(&key);result}
}
reader.rs
use std::fs::{File, OpenOptions};
use std::io::{BufReader, Read, Seek, SeekFrom};use serde_json::Deserializer;use crate::cmd::{Command, CommandPosition, Index};use super::KvResult;pub struct PosBufReader {reader: BufReader<File>,
}impl PosBufReader {pub fn new(path: &str) -> anyhow::Result<PosBufReader> {let file = OpenOptions::new().read(true).open(path)?;let reader = BufReader::new(file);Ok(Self { reader })}pub fn load(&mut self, map: &mut Index) -> anyhow::Result<()> {let reader = &mut self.reader;let mut old = reader.seek(SeekFrom::Start(0))? as usize;let mut stream = Deserializer::from_reader(reader).into_iter();while let Some(cmd) = stream.next() {let new = stream.byte_offset();match cmd? {Command::Set { key, .. } => {let position = CommandPosition::new(old, new - old);map.insert(key, position);}Command::Remove { .. } => (),};old = new;}Ok(())}pub fn read(&mut self, position: Option<&CommandPosition>) -> KvResult {let position = match position {Some(position) => position,None => return Ok(None),};self.reader.seek(SeekFrom::Start(position.pos as u64))?;let command = (&mut self.reader).take(position.len as u64);match serde_json::from_reader(command)? {Command::Set { value, .. } => Ok(Some(value)),_ => unreachable!(),}}
}
总结
读取值时,根据内存中保存的索引,到文件中获取真正的值。