环境
- Time 2022-12-11
- 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::HashMap;
use std::fs::{File, OpenOptions};
use std::io::{BufWriter, Write};use anyhow::{Ok, Result};use crate::cmd::Command;mod reader;pub(crate) struct CommandLog {writer: BufWriter<File>,map: HashMap<String, String>,
}pub type KvResult = Result<Option<String>>;impl CommandLog {pub(crate) fn new() -> Result<Self> {let path = "/root/log/1.log";let writer = new_writer(path)?;let mut map = HashMap::default();reader::load(path, &mut map)?;Ok(Self { writer, map })}pub(crate) fn get(&mut self, key: &str) -> KvResult {Ok(self.map.get(key).map(String::from))}pub fn set(&mut self, key: String, value: String) -> KvResult {let command = Command::Set {key: key.to_string(),value: value.to_string(),};let json = serde_json::to_string(&command)?;self.writer.write_all(json.as_bytes())?;Ok(self.map.insert(key, value))}pub(crate) fn remove(&mut self, key: String) -> KvResult {let command = Command::Remove { key: &key };let json = serde_json::to_string(&command)?;self.writer.write_all(json.as_bytes())?;Ok(self.map.remove(&key))}
}fn new_writer(path: &str) -> Result<BufWriter<File>> {let file = OpenOptions::new().append(true).create(true).open(path)?;Ok(BufWriter::new(file))
}
reader.rs
use std::collections::HashMap;
use std::fs::{File, OpenOptions};
use std::io::BufReader;use anyhow::Result;
use serde_json::Deserializer;use crate::cmd::Command;pub fn load(path: &str, map: &mut HashMap<String, String>) -> Result<()> {let stream = Deserializer::from_reader(new_reader(path)?).into_iter();for cmd in stream {match cmd? {Command::Set { key, value } => map.insert(key, value),Command::Remove { key } => map.remove(key),};}Ok(())
}fn new_reader(path: &str) -> Result<BufReader<File>> {let file = OpenOptions::new().read(true).open(path)?;Ok(BufReader::new(file))
}
运行
使用 cargo build --release 构建后运行。
root@jiangbo12490:~/git/game/target/release# ./kvs set name JiangBo
SET KEY: name, VALUE: None
root@jiangbo12490:~/git/game/target/release# ./kvs set name ZhangSan
SET KEY: name, VALUE: JiangBo
root@jiangbo12490:~/git/game/target/release# ./kvs get name
GET KEY: name, VALUE: ZhangSan
root@jiangbo12490:~/git/game/target/release# ./kvs rm name
REM KEY: name, VALUE: ZhangSan
查看文件
root@jiangbo12490:~/log# cat 1.log
{"Set":{"key":"name","value":"JiangBo"}}{"Set":{"key":"name","value":"ZhangSan"}}{"Remove":{"key":"name"}}
总结
将读取文件的逻辑分离到了单独的文件中。