| Crates.io | kotoba-db-engine-lsm |
| lib.rs | kotoba-db-engine-lsm |
| version | 0.1.16 |
| created_at | 2025-09-18 03:02:43.624368+00 |
| updated_at | 2025-09-18 03:02:43.624368+00 |
| description | LSM-Tree based database engine for KotobaDB |
| homepage | https://github.com/com-junkawasaki/kotoba |
| repository | https://github.com/com-junkawasaki/kotoba |
| max_upload_size | |
| id | 1844194 |
| size | 95,046 |
High-performance LSM-Tree based storage engine for KotobaDB. This engine provides persistent storage with excellent write performance and efficient read operations.
The LSM (Log-Structured Merge-Tree) engine is the primary persistent storage backend for KotobaDB. It provides:
┌─────────────────────────────────────┐
│ Application Layer │
├─────────────────────────────────────┤
│ WAL (Durability) │ ← Write-ahead log
├─────────────────────────────────────┤
│ MemTable (Active) │ ← In-memory buffer
├─────────────────────────────────────┤
│ SSTable Files (L0-Ln) │ ← Sorted, immutable files
│ ┌─────────────────────────────────┐ │
│ │ Bloom Filter | Data | Index │ │
│ └─────────────────────────────────┘ │
├─────────────────────────────────────┤
│ Compaction Manager │ ← Background optimization
└─────────────────────────────────────┘
Ensures durability by logging all changes before they reach the MemTable:
pub struct WAL {
file: tokio::fs::File,
buffer: Vec<u8>,
}
In-memory buffer for recent writes:
pub struct LSMStorageEngine {
memtable: Arc<RwLock<BTreeMap<Vec<u8>, Vec<u8>>>>,
// ...
}
Sorted, immutable files on disk:
pub struct SSTableHandle {
path: PathBuf,
min_key: Vec<u8>,
max_key: Vec<u8>,
bloom_filter: BloomFilter,
}
Probabilistic data structure for fast existence checks:
pub struct BloomFilter {
bits: Vec<u8>,
num_hashes: usize,
size: usize,
}
#[derive(Clone)]
pub struct CompactionConfig {
/// Maximum SSTable files before triggering compaction
pub max_sstables: usize,
/// Minimum files to compact together
pub min_compaction_files: usize,
}
impl Default for CompactionConfig {
fn default() -> Self {
Self {
max_sstables: 10,
min_compaction_files: 4,
}
}
}
use kotoba_db_engine_lsm::LSMStorageEngine;
// Create/open database
let mut engine = LSMStorageEngine::new("./my_db").await?;
// Or with custom config
let config = CompactionConfig {
max_sstables: 20,
min_compaction_files: 6,
};
let mut engine = LSMStorageEngine::with_config("./my_db", config).await?;
// Basic operations
engine.put(b"key1", b"value1").await?;
let value = engine.get(b"key1").await?;
assert_eq!(value, Some(b"value1".to_vec()));
engine.delete(b"key1").await?;
let value = engine.get(b"key1").await?;
assert_eq!(value, None);
// Scan all keys with prefix
let results = engine.scan(b"user:").await?;
for (key, value) in results {
println!("{:?}: {:?}", key, value);
}
if sstables.len() >= self.compaction_config.max_sstables {
self.perform_compaction().await?;
}
// Get storage statistics
let stats = engine.get_stats().await?;
println!("SSTable count: {}", stats.sstable_count);
println!("Total size: {} bytes", stats.total_size);
println!("Read ops: {}", stats.read_operations);
// Manual compaction
engine.force_compaction().await?;
// Cleanup old WAL files
engine.cleanup_wal().await?;
// Validate data integrity
engine.validate_integrity().await?;
The LSM engine integrates seamlessly with the KotobaDB API:
use kotoba_db::{DB, StorageEngine};
use kotoba_db_engine_lsm::LSMStorageEngine;
// Create LSM engine
let lsm_engine = LSMStorageEngine::new("./data").await?;
// Create DB with LSM backend
let db = DB::with_engine(Box::new(lsm_engine)).await?;
let config = CompactionConfig {
max_sstables: 20, // More SSTables before compaction
min_compaction_files: 8, // Larger compaction batches
};
let config = CompactionConfig {
max_sstables: 5, // Fewer SSTables for faster reads
min_compaction_files: 2, // Smaller compaction batches
};
let config = CompactionConfig {
max_sstables: 3, // Very aggressive compaction
min_compaction_files: 2, // Minimal batches
};
The engine provides comprehensive error handling:
use anyhow::Result;
async fn database_operation(engine: &mut LSMStorageEngine) -> Result<()> {
match engine.put(b"key", b"value").await {
Ok(()) => println!("Write successful"),
Err(e) => {
eprintln!("Write failed: {}", e);
// Handle specific error types
if let Some(io_err) = e.downcast_ref::<std::io::Error>() {
// Handle I/O errors
}
}
}
Ok(())
}
# Run unit tests
cargo test --package kotoba-db-engine-lsm
# Run with all features
cargo test --package kotoba-db-engine-lsm --all-features
# Run benchmarks
cargo bench --package kotoba-db-engine-lsm
anyhow: Error handlingtokio: Async runtimeasync-trait: Async traitskotoba-db-core: Core types and traits[Bloom Filter Size: u32][Bloom Filter Bytes][Data Size: u32][Data]
[Key Length: u32][Key][Value Length: u32][Value]...
[Key Length: u32][Key][Value Length: u32][Value]...
Licensed under the MIT License.