### Install Rust via rustup Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Use this command to install the Rust programming language toolchain. Follow the on-screen instructions for your operating system. Verify the installation by running `rustc -V`. ```bash curl https://sh.rustup.rs -sSf | sh ``` -------------------------------- ### Criterion Benchmark with Setup Outside Iteration Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-4/README.md Shows how to perform setup operations outside the `b.iter` closure in a Criterion benchmark. This is crucial for benchmarks where setup is expensive and should not be included in the measured time. The setup code runs once before the iterations begin. ```rust let c = Criterion::default(); let inputs = &[1, 2, 3, 4, 5]; c.bench_function_over_inputs("example", |b, &&num| { // do setup here b.iter(|| { // important measured work goes here }); }, inputs); ``` -------------------------------- ### kvs-server CLI Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-3/README.md Commands to start and manage the key-value store server. ```APIDOC ## kvs-server ### Description Starts the key-value store server and listens for incoming connections. ### Parameters #### Options - **--addr** (IP:PORT) - Optional - The IP address and port to listen on. Defaults to 127.0.0.1:4000. - **--engine** (string) - Optional - The storage engine to use: 'kvs' or 'sled'. - **-V** (flag) - Optional - Print the version. ``` -------------------------------- ### Execute Transaction Example Source: https://context7.com/pingcap/talent-plan/llms.txt Demonstrates the workflow of beginning a transaction, performing reads and buffered writes, and committing the changes. ```rust // Example usage: fn transaction_example(client: &mut Client) -> Result<()> { client.begin(); // Read existing value let balance = client.get(b"account_a".to_vec())?; // Perform writes (buffered until commit) client.set(b"account_a".to_vec(), b"900".to_vec()); client.set(b"account_b".to_vec(), b"100".to_vec()); // Commit transaction atomically let success = client.commit()?; assert!(success); Ok(()) } ``` -------------------------------- ### Install Rust Toolchain Components Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Use rustup to add the clippy and rustfmt components to your local Rust toolchain. ```shell rustup component add clippy rustup component add rustfmt ``` -------------------------------- ### SledKvsEngine Implementation Source: https://context7.com/pingcap/talent-plan/llms.txt An example implementation of the KvsEngine trait using the sled embedded database. ```APIDOC ## Struct SledKvsEngine ### Description Example implementation wrapper for sled. ### Methods - `open(path: impl AsRef) -> Result`: Opens a new SledKvsEngine at the specified path. ### Implements `KvsEngine` - `set(&self, key: String, value: String) -> Result<()>`: Inserts a key-value pair into the sled database and flushes the changes. - `get(&self, key: String) -> Result>`: Retrieves the value associated with a key from the sled database. - `remove(&self, key: String) -> Result<()>`: Removes a key-value pair from the sled database and flushes the changes. Returns `KvsError::KeyNotFound` if the key does not exist. ``` -------------------------------- ### Analyze Use Statement Path Resolution Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Example showing how the compiler identifies a missing crate based on the first element of a use path. ```text 1 | use assert_cmd::prelude::*; | ^^^^^^^^^^ use of undeclared type or module `assert_cmd` ``` -------------------------------- ### Multithreaded Server Example Source: https://context7.com/pingcap/talent-plan/llms.txt Demonstrates using SharedQueueThreadPool to handle incoming TCP connections concurrently in a server application. ```rust // Example multithreaded server usage: fn main() -> Result<()> { let engine = KvStore::open("./data")?; let pool = SharedQueueThreadPool::new(num_cpus::get() as u32)?; let listener = TcpListener::bind("127.0.0.1:4000")?; for stream in listener.incoming() { let engine = engine.clone(); pool.spawn(move || { // Handle connection on worker thread handle_client(stream.unwrap(), engine); }); } Ok(()) } ``` -------------------------------- ### Define Client::get future signatures Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-5/README.md Examples of different ways to define the return type for the asynchronous get method in the KvsClient. ```rust Client::get(&mut self, key: String) -> Box, Error = Error> ``` ```rust Client::get(&mut self, key: String) -> future::SomeExplicitCombinator<...> ``` ```rust Client::get(&mut self, key: String) -> impl Future, Error = Error> ``` ```rust Client::get(&mut self, key: String) -> ClientGetFuture ``` -------------------------------- ### kvs.rs Main Function Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md The `kvs.rs` file contains the main function for the binary executable. This example prints 'Hello, world!' to the console. ```rust fn main() { println!("Hello, world!"); } ``` -------------------------------- ### Identify Missing Crate Errors Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Example of compiler output indicating that a crate is missing from the project manifest. ```text error[E0433]: failed to resolve: use of undeclared type or module `assert_cmd` --> tests/tests.rs:1:5 | 1 | use assert_cmd::prelude::*; | ^^^^^^^^^^ use of undeclared type or module `assert_cmd` error[E0432]: unresolved import --> tests/tests.rs:3:5 | 3 | use predicates::str::contains; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ``` -------------------------------- ### View Cargo Test Output Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Example output from running cargo test showing multiple test targets. ```text Running target/debug/deps/kvs-b03a01e7008067f6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/kvs-a3b5a004932c6715 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/tests-5e1c2e20bd1fa377 running 13 tests test cli_get ... FAILED ``` -------------------------------- ### View Test Execution Results Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Example output from running cargo test showing failed test cases. ```text Finished dev [unoptimized + debuginfo] target(s) in 2.32s Running target/debug/deps/kvs-b03a01e7008067f6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/kvs-a3b5a004932c6715 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/tests-5e1c2e20bd1fa377 running 13 tests test cli_get ... FAILED test cli_invalid_get ... FAILED test cli_invalid_rm ... FAILED ``` -------------------------------- ### Implement KvsEngine for sled Crate Source: https://context7.com/pingcap/talent-plan/llms.txt This implementation adapts the sled key-value store to the KvsEngine trait. It includes methods for opening a sled database, setting, getting, and removing key-value pairs. Ensure sled is added as a dependency. ```rust // Example implementation wrapper for sled: use sled::Db; #[derive(Clone)] pub struct SledKvsEngine { db: Db, } impl SledKvsEngine { pub fn open(path: impl AsRef) -> Result { let db = sled::open(path)?; Ok(SledKvsEngine { db }) } } impl KvsEngine for SledKvsEngine { fn set(&self, key: String, value: String) -> Result<()> { self.db.insert(key.as_bytes(), value.as_bytes())?; self.db.flush()?; Ok(()) } fn get(&self, key: String) -> Result> { Ok(self.db.get(key.as_bytes())? .map(|v| String::from_utf8_lossy(&v).to_string())) } fn remove(&self, key: String) -> Result<()> { self.db.remove(key.as_bytes())?; self.db.flush()?; Ok(()) } } ``` -------------------------------- ### Implement CLI with clap in Rust Source: https://context7.com/pingcap/talent-plan/llms.txt Uses clap to define subcommands for set, get, and rm operations with default address configuration. Requires the clap crate and assumes the existence of a KvsClient struct with connection and operation methods. ```rust use clap::{App, Arg, SubCommand}; use std::net::SocketAddr; fn main() { let matches = App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .author(env!("CARGO_PKG_AUTHORS")) .about(env!("CARGO_PKG_DESCRIPTION")) .subcommand( SubCommand::with_name("set") .about("Set the value of a string key") .arg(Arg::with_name("KEY").required(true)) .arg(Arg::with_name("VALUE").required(true)) .arg( Arg::with_name("addr") .long("addr") .takes_value(true) .default_value("127.0.0.1:4000"), ), ) .subcommand( SubCommand::with_name("get") .about("Get the string value of a key") .arg(Arg::with_name("KEY").required(true)) .arg( Arg::with_name("addr") .long("addr") .takes_value(true) .default_value("127.0.0.1:4000"), ), ) .subcommand( SubCommand::with_name("rm") .about("Remove a given key") .arg(Arg::with_name("KEY").required(true)) .arg( Arg::with_name("addr") .long("addr") .takes_value(true) .default_value("127.0.0.1:4000"), ), ) .get_matches(); match matches.subcommand() { ("set", Some(m)) => { let key = m.value_of("KEY").unwrap(); let value = m.value_of("VALUE").unwrap(); let addr: SocketAddr = m.value_of("addr").unwrap().parse().unwrap(); let mut client = KvsClient::connect(addr).unwrap(); client.set(key.to_string(), value.to_string()).unwrap(); } ("get", Some(m)) => { let key = m.value_of("KEY").unwrap(); let addr: SocketAddr = m.value_of("addr").unwrap().parse().unwrap(); let mut client = KvsClient::connect(addr).unwrap(); match client.get(key.to_string()).unwrap() { Some(value) => println!("{}", value), None => println!("Key not found"), } } ("rm", Some(m)) => { let key = m.value_of("KEY").unwrap(); let addr: SocketAddr = m.value_of("addr").unwrap().parse().unwrap(); let mut client = KvsClient::connect(addr).unwrap(); client.remove(key.to_string()).unwrap(); } _ => unreachable!(), } } ``` -------------------------------- ### Implement In-Memory KvStore in Rust Source: https://context7.com/pingcap/talent-plan/llms.txt Defines a basic KvStore structure using a HashMap for in-memory storage and provides methods for set, get, and remove operations. ```rust use std::collections::HashMap; /// The `KvStore` stores string key/value pairs. /// /// Key/value pairs are stored in a `HashMap` in memory and not persisted to disk. #[derive(Default)] pub struct KvStore { map: HashMap, } impl KvStore { /// Creates a `KvStore`. pub fn new() -> KvStore { KvStore { map: HashMap::new(), } } /// Sets the value of a string key to a string. /// If the key already exists, the previous value will be overwritten. pub fn set(&mut self, key: String, value: String) { self.map.insert(key, value); } /// Gets the string value of a given string key. /// Returns `None` if the given key does not exist. pub fn get(&self, key: String) -> Option { self.map.get(&key).cloned() } /// Remove a given key. pub fn remove(&mut self, key: String) { self.map.remove(&key); } } // Example usage: fn main() { let mut store = KvStore::new(); store.set("key1".to_owned(), "value1".to_owned()); let val = store.get("key1".to_owned()); assert_eq!(val, Some("value1".to_owned())); store.remove("key1".to_owned()); assert_eq!(store.get("key1".to_owned()), None); } ``` -------------------------------- ### KvStore::open Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-2/README.md Initializes and opens the KvStore at a specified file path. ```APIDOC ## KvStore::open ### Description Opens the KvStore at a given path and returns the KvStore instance. ### Parameters - **path** (impl Into) - Required - The file system path where the store is located. ### Response - **Result** - Returns the initialized KvStore instance or an error if the operation fails. ``` -------------------------------- ### Access Test Binary Help Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Use the double-dash separator to pass arguments directly to the compiled test executable. ```bash cargo test -- --help ``` -------------------------------- ### Simulate RPC communication with labrpc Source: https://context7.com/pingcap/talent-plan/llms.txt Demonstrates defining a service with the service! macro, implementing the service trait, and setting up a simulated network environment. ```rust use futures::executor::block_on; use prost_derive::Message; use labrpc::*; /// Define protobuf message with prost. #[derive(Clone, PartialEq, Message)] pub struct Echo { #[prost(int64, tag = "1")] pub x: i64, } // Define RPC service using the service! macro. service! { service echo { rpc ping(Echo) returns (Echo); } } use echo::{add_service, Client, Service}; /// Implement the service trait. #[derive(Clone)] struct EchoService; #[async_trait::async_trait] impl Service for EchoService { async fn ping(&self, input: Echo) -> Result { Ok(input) } } fn main() { // Create simulated network let rn = Network::new(); // Create and register server let server_name = "echo_server"; let mut builder = ServerBuilder::new(server_name.to_owned()); add_service(EchoService, &mut builder).unwrap(); let server = builder.build(); rn.add_server(server); // Create client let client_name = "client"; let client = Client::new(rn.create_client(client_name.to_owned())); rn.enable(client_name, true); rn.connect(client_name, server_name); // Make RPC call let reply = block_on(async { client.ping(&Echo { x: 777 }).await.unwrap() }); assert_eq!(reply, Echo { x: 777 }); println!("{:?}", reply); } ``` -------------------------------- ### Project Directory Structure Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md This is the standard directory layout for the project, including the manifest, source code, binary, library, and tests. ```text ├── Cargo.toml ├── src │   ├── bin │   │   └── kvs.rs │   └── lib.rs └── tests └── tests.rs ``` -------------------------------- ### Run CLI with arguments Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Use this command pattern to pass arguments to the application during development. ```bash cargo run -- get key1 ``` -------------------------------- ### KvsEngine Trait Definition Source: https://context7.com/pingcap/talent-plan/llms.txt Defines the core interface for key-value storage engines, including set, get, and remove operations. ```APIDOC ## Trait KvsEngine ### Description Trait for key-value storage engines. Enables pluggable storage backends. ### Methods - `set(&self, key: String, value: String) -> Result<()>`: Sets the value of a string key to a string. Returns an error if the value is not written successfully. - `get(&self, key: String) -> Result>`: Gets the string value of a string key. Returns `None` if the key does not exist. Returns an error if the value is not read successfully. - `remove(&self, key: String) -> Result<()>`: Removes a given string key. Returns an error if the key does not exist or is not removed successfully. ``` -------------------------------- ### Execute Test Binary Directly Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Run a specific test binary from the target directory to inspect its behavior. ```bash target/debug/deps/kvs-b03a01e7008067f6 --help ``` -------------------------------- ### Basic Criterion Parameterized Benchmark Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-4/README.md Demonstrates how to set up a basic parameterized benchmark using Criterion. The `inputs` array defines the parameters, and `bench_function_over_inputs` runs the benchmark for each input. The closure passed to `b.iter` contains the code to be measured. ```rust let c = Criterion::default(); let inputs = &[1, 2, 3, 4, 5]; c.bench_function_over_inputs("example", |b, &&num| { b.iter(|| { // important measured work goes here }); }, inputs); ``` -------------------------------- ### Define Thread Pool Messages in Rust Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-4/README.md Use an enum to define the types of messages that can be sent between threads in a thread pool. This example includes a variant for running a job and another for shutting down the pool. ```rust enum ThreadPoolMessage { RunJob(Box), Shutdown, } ``` -------------------------------- ### Implement TCP Client-Server for Key-Value Store Source: https://context7.com/pingcap/talent-plan/llms.txt Defines the Request and Response protocols, the KvsClient for network communication, and the KvsServer for handling incoming TCP connections. ```rust use std::net::{TcpListener, TcpStream, SocketAddr}; use std::io::{BufReader, BufWriter}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub enum Request { Get { key: String }, Set { key: String, value: String }, Remove { key: String }, } #[derive(Serialize, Deserialize, Debug)] pub enum Response { Ok(Option), Err(String), } /// Key-value store client. pub struct KvsClient { reader: BufReader, writer: BufWriter, } impl KvsClient { /// Connect to a server at the given address. pub fn connect(addr: SocketAddr) -> Result { let stream = TcpStream::connect(addr)?; let reader = BufReader::new(stream.try_clone()?); let writer = BufWriter::new(stream); Ok(KvsClient { reader, writer }) } /// Get the value for a key from the server. pub fn get(&mut self, key: String) -> Result> { serde_json::to_writer(&mut self.writer, &Request::Get { key })?; self.writer.flush()?; let response: Response = serde_json::from_reader(&mut self.reader)?; match response { Response::Ok(value) => Ok(value), Response::Err(msg) => Err(KvsError::StringError(msg)), } } /// Set a key-value pair on the server. pub fn set(&mut self, key: String, value: String) -> Result<()> { serde_json::to_writer(&mut self.writer, &Request::Set { key, value })?; self.writer.flush()?; let response: Response = serde_json::from_reader(&mut self.reader)?; match response { Response::Ok(_) => Ok(()), Response::Err(msg) => Err(KvsError::StringError(msg)), } } } /// Key-value store server. pub struct KvsServer { engine: E, } impl KvsServer { pub fn new(engine: E) -> Self { KvsServer { engine } } /// Run the server listening on the given address. pub fn run(&mut self, addr: SocketAddr) -> Result<()> { let listener = TcpListener::bind(addr)?; for stream in listener.incoming() { let stream = stream?; self.handle_connection(stream)?; } Ok(()) } fn handle_connection(&mut self, stream: TcpStream) -> Result<()> { let reader = BufReader::new(&stream); let mut writer = BufWriter::new(&stream); let request: Request = serde_json::from_reader(reader)?; let response = match request { Request::Get { key } => { match self.engine.get(key) { Ok(value) => Response::Ok(value), Err(e) => Response::Err(format!("{}", e)), } } Request::Set { key, value } => { match self.engine.set(key, value) { Ok(_) => Response::Ok(None), Err(e) => Response::Err(format!("{}", e)), } } Request::Remove { key } => { match self.engine.remove(key) { Ok(_) => Response::Ok(None), Err(e) => Response::Err(format!("{}", e)), } } }; serde_json::to_writer(&mut writer, &response)?; writer.flush()?; Ok(()) } } ``` -------------------------------- ### Format project and lesson headers Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/CONTRIBUTING.md Use sentence case for headers, capitalizing only the first word and words following a colon. ```markdown ## Project spec ## Lesson: Tools and good bones ``` -------------------------------- ### Define KvsEngine Trait for Key-Value Storage Source: https://context7.com/pingcap/talent-plan/llms.txt This trait defines the core interface for key-value storage engines, including set, get, and remove operations. It requires implementations to be cloneable, sendable across threads, and have a static lifetime. ```rust /// Trait for key-value storage engines. pub trait KvsEngine: Clone + Send + 'static { /// Sets the value of a string key to a string. /// Return an error if the value is not written successfully. fn set(&self, key: String, value: String) -> Result<()>; /// Gets the string value of a string key. /// If the key does not exist, return `None`. /// Return an error if the value is not read successfully. fn get(&self, key: String) -> Result>; /// Removes a given string key. /// Return an error if the key does not exist or is not removed successfully. fn remove(&self, key: String) -> Result<()>; } ``` -------------------------------- ### Implement KvStore with Log-Structured Storage in Rust Source: https://context7.com/pingcap/talent-plan/llms.txt This Rust code defines the KvStore, a persistent key-value store. It uses log-structured file I/O with automatic compaction and an in-memory BTreeMap index. Ensure necessary imports and dependencies are included. ```rust use std::collections::BTreeMap; use std::fs::{self, File, OpenOptions}; use std::io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::path::PathBuf; use serde::{Deserialize, Serialize}; const COMPACTION_THRESHOLD: u64 = 1024 * 1024; /// Struct representing a command. #[derive(Serialize, Deserialize, Debug)] enum Command { Set { key: String, value: String }, Remove { key: String }, } /// Represents the position and length of a command in the log. struct CommandPos { gen: u64, pos: u64, len: u64, } /// Persistent key/value store with log-structured storage. pub struct KvStore { path: PathBuf, readers: HashMap>, writer: BufWriterWithPos, current_gen: u64, index: BTreeMap, uncompacted: u64, } impl KvStore { /// Opens a KvStore at the given path. /// Creates a new directory if it doesn't exist. pub fn open(path: impl Into) -> Result { let path = path.into(); fs::create_dir_all(&path)?; // Load existing logs and rebuild index... Ok(KvStore { /* ... */ }) } /// Sets a key to a value, persisting to the log. pub fn set(&mut self, key: String, value: String) -> Result<()> { let cmd = Command::Set { key: key.clone(), value }; let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; // Update index with new position self.index.insert(key, CommandPos { gen: self.current_gen, pos, len: self.writer.pos - pos, }); // Trigger compaction if threshold exceeded if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } /// Gets the value for a key by reading from the log. pub fn get(&mut self, key: String) -> Result> { if let Some(cmd_pos) = self.index.get(&key) { let reader = self.readers.get_mut(&cmd_pos.gen).unwrap(); reader.seek(SeekFrom::Start(cmd_pos.pos))?; let cmd_reader = reader.take(cmd_pos.len); if let Command::Set { value, .. } = serde_json::from_reader(cmd_reader)? { Ok(Some(value)) } else { Err(KvsError::UnexpectedCommandType) } } else { Ok(None) } } /// Removes a key from the store. pub fn remove(&mut self, key: String) -> Result<()> { if self.index.contains_key(&key) { let cmd = Command::Remove { key: key.clone() }; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; self.index.remove(&key); Ok(()) } else { Err(KvsError::KeyNotFound) } } } ``` ```rust use std::env::current_dir; // Example usage: fn main() -> Result<()> { let mut store = KvStore::open(current_dir()?)?; store.set("key".to_owned(), "value".to_owned())?; let val = store.get("key".to_owned())?; assert_eq!(val, Some("value".to_owned())); store.remove("key".to_owned())?; assert_eq!(store.get("key".to_owned())?, None); Ok(()) } ``` -------------------------------- ### lib.rs Boilerplate Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md The `lib.rs` file serves as the entry point for the library part of the crate. It can be left empty initially. ```rust // just leave it empty for now ``` -------------------------------- ### KvServer Request Handling Loop Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-4/README.md This loop demonstrates how KvServer processes incoming TCP connections. Each connection's request is read, processed via KvsEngine, and a response is sent back. This version is intended to be modified to spawn work into a NaiveThreadPool. ```rust let listener = TcpListener::bind(addr)?; for stream in listener.incoming() { let cmd = self.read_cmd(&stream); let resp = self.process_cmd(cmd); self.respond(&stream, resp); } ``` -------------------------------- ### Visualize request serialization Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-4/README.md Diagram illustrating how requests are processed sequentially on a single thread. ```text thread + +--------+--------+--------+--------+ T1 | | R1 | R2 | W1 | W2 | + +--------+--------+--------+--------+ --> read/write reqs over time --> ``` -------------------------------- ### Configure Cargo Development Dependencies Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Add these lines to your Cargo.toml file to resolve missing crate errors during testing. ```toml [dev-dependencies] assert_cmd = "0.11.0" predicates = "1.0.0" ``` -------------------------------- ### kvs-client CLI Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-3/README.md Commands for the client to interact with the kvs-server. ```APIDOC ## kvs-client set ### Description Sets the value of a string key. ### Parameters - **KEY** (string) - Required - The key to set. - **VALUE** (string) - Required - The value to associate with the key. - **--addr** (IP:PORT) - Optional - The server address to connect to. Defaults to 127.0.0.1:4000. ## kvs-client get ### Description Retrieves the value of a string key. ### Parameters - **KEY** (string) - Required - The key to retrieve. - **--addr** (IP:PORT) - Optional - The server address to connect to. Defaults to 127.0.0.1:4000. ## kvs-client rm ### Description Removes a string key from the store. ### Parameters - **KEY** (string) - Required - The key to remove. - **--addr** (IP:PORT) - Optional - The server address to connect to. Defaults to 127.0.0.1:4000. ``` -------------------------------- ### CLI Commands Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-1/README.md Command-line interface specifications for the kvs executable. ```APIDOC ## CLI Commands ### Description The kvs executable supports various command-line arguments to interact with the key-value store. ### Commands - `kvs set ` - Set the value of a string key to a string - `kvs get ` - Get the string value of a given string key - `kvs rm ` - Remove a given key - `kvs -V` - Print the version ``` -------------------------------- ### KvStore::set Source: https://github.com/pingcap/talent-plan/blob/master/courses/rust/projects/project-2/README.md Sets the value of a string key to a string. ```APIDOC ## KvStore::set ### Description Sets the value of a string key to a string. Writes the command to a sequential log and updates the in-memory index. ### Parameters - **key** (String) - Required - The key to set. - **value** (String) - Required - The value to associate with the key. ### Response - **Result<()>** - Returns an error if the value is not written successfully. ```