# GrausDb ![Rust](https://img.shields.io/badge/Rust-1.53+-orange) ![License](https://img.shields.io/badge/license-MIT-blue) GrausDb is a high-performance, thread-safe key-value embedded data store written in Rust. It is designed for simplicity, efficiency, and reliability. ## Features - **Lock-Free Concurrency:** GrausDb leverages lock-free data structures for high-performance concurrent access. - **Persistence:** Data is persisted to disk for durability. - **Log-Based Storage:** Key-value pairs are stored in log files. - **Benchmarks:** Benchmarks included to assess the performance. ## Installation To use GrausDb in your Rust project, simply add it as a dependency in your `Cargo.toml` file: ```toml [dependencies] graus_db = "0.1.0" ``` ## Quick start Here's a quick example of how to use GrausDb in your Rust application: ```rust let store = GrausDb::open("path")?; store.set("key".to_owned(), "value".to_owned())?; let val = store.get("key".to_owned())?; ``` It can also be called from multiple threads: ```rust let store = GrausDb::open("path")?; // Calls set method from 8 different threads for i in 0..8 { let store = store.clone(); thread::spawn(move || { store.set(format!("key{}", i), format!("value{}", i)).unwrap(); }); } ``` ## API GrausDb provides a simple and intuitive API for interacting with the key-value store. Below are some of the key functions and methods exposed by GrausDb, along with usage examples. ### `GrausDb::open` `open` is used to open a GrausDb instance, creating a new database if it doesn't exist at the specified path. #### Example: ```rust use graus_db::{GrausDb, Result}; fn main() -> Result<()> { let store = GrausDb::open("my_database")?; // Your database is now ready to use. Ok(()) } ``` ### `set` The `set` method is used to store a key-value pair in the database. #### Example: ```rust use graus_db::{GrausDb, Result}; fn main() -> Result<()> { let store = GrausDb::open("my_database")?; store.set("key".to_owned(), "value".to_owned())?; // Key "key" now has the value "value" in the database. Ok(()) } ``` ### `get` The `get` method retrieves the value associated with a given key. #### Example: ```rust use graus_db::{GrausDb, Result}; fn main() -> Result<()> { let store = GrausDb::open("my_database")?; store.set("key".to_owned(), "value".to_owned())?; if let Some(value) = store.get("key".to_owned())? { println!("Value: {}", value); // Outputs: "Value: value" } else { println!("Key not found"); } Ok(()) } ``` ### `remove` The `remove` method deletes a key and its associated value from the database. #### Example: ```rust use graus_db::{GrausDb, Result}; fn main() -> Result<()> { let store = GrausDb::open("my_database")?; store.set("key".to_owned(), "value".to_owned())?; store.remove("key".to_owned())?; // Key "key" and its value are now removed from the database. Ok(()) } ``` ### `update_if` The `update_if` method updates the value of an existing key atomically, allowing you to provide a custom update function. An optional predicate can be passed, the value will only be updated if the predicate is satisfied. #### Example: ```rust use graus_db::{GrausDb, Result}; fn main() -> Result<()> { let key = ¨key1¨; store.set(key.to_owned(), "25".to_owned()).unwrap(); let update_fn = |value: String| { let num = value.parse::().unwrap(); (num - 1).to_string() }; let predicate = |value: String| { let num = value.parse::().unwrap(); num > 0 }; let result = store.update_if( key.to_owned(), update_fn, Some(key.to_owned()), Some(predicate), ); // Key "key1" now has the value "24" in the database. // The function was applied because the predicate was met (25 > 0) } ``` For more details on how to use GrausDb, please refer to the tests. ## Architecture and Implementation GrausDb's architecture is built around the principles of log-based storage and lock-free concurrency: - Log-Based Storage: GrausDb stores key-value pairs in log files. Log files are named after monotonically increasing generation numbers with a log extension. This design ensures that data is durably persisted to disk. - Lock-Free Concurrency: GrausDb uses lock-free data structures to provide high-performance concurrent access to the data. This enables multiple threads to interact with the database efficiently. - In-Memory Index: GrausDb maintains an in-memory index that maps keys to their positions in the log. This index allows for fast lookups and efficient data retrieval. - Compaction: To maintain efficient storage and reduce disk space usage, GrausDb performs compaction when a threshold is reached. Compaction involves rewriting log files, removing stale data, and reclaiming disk space. ## Benchmarks GrausDb includes built-in benchmarking tools to evaluate its efficiency and to help you make data-driven decisions. ## Future Development Next features: - Multithread benchmark - Range get - Sync API (journal) - Internal threadpool + futures ### License GrausDb is licensed under the MIT License. Happy coding with GrausDb! ## Contact GrausDb is created and maintained by **Ricardo Pallas**. Website: [https://rpallas92.github.io/](https://rpallas92.github.io/)