0288-KVS-根据索引读取文件
环境
- 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!(),
}
}
}
总结
读取值时,根据内存中保存的索引,到文件中获取真正的值。

浙公网安备 33010602011771号