200 lines
6.4 KiB
Rust
200 lines
6.4 KiB
Rust
use ourdb::{OurDB, OurDBConfig, OurDBSetArgs};
|
|
use std::path::PathBuf;
|
|
use std::time::Instant;
|
|
|
|
fn main() -> Result<(), ourdb::Error> {
|
|
// Create a temporary directory for the database
|
|
let db_path = std::env::temp_dir().join("ourdb_advanced_example");
|
|
std::fs::create_dir_all(&db_path)?;
|
|
|
|
println!("Creating database at: {}", db_path.display());
|
|
|
|
// Demonstrate key-value mode (non-incremental)
|
|
key_value_mode_example(&db_path)?;
|
|
|
|
// Demonstrate incremental mode
|
|
incremental_mode_example(&db_path)?;
|
|
|
|
// Demonstrate performance benchmarking
|
|
performance_benchmark(&db_path)?;
|
|
|
|
// Clean up (optional)
|
|
if std::env::var("KEEP_DB").is_err() {
|
|
std::fs::remove_dir_all(&db_path)?;
|
|
println!("Cleaned up database directory");
|
|
} else {
|
|
println!("Database kept at: {}", db_path.display());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn key_value_mode_example(base_path: &PathBuf) -> Result<(), ourdb::Error> {
|
|
println!("\n=== Key-Value Mode Example ===");
|
|
|
|
let db_path = base_path.join("key_value");
|
|
std::fs::create_dir_all(&db_path)?;
|
|
|
|
// Create a new database with key-value mode (non-incremental)
|
|
let config = OurDBConfig {
|
|
path: db_path,
|
|
incremental_mode: false,
|
|
file_size: Some(1024 * 1024), // 1MB for testing
|
|
keysize: Some(2), // Small key size for demonstration
|
|
};
|
|
|
|
let mut db = OurDB::new(config)?;
|
|
|
|
// In key-value mode, we must provide IDs explicitly
|
|
let custom_ids = [100, 200, 300, 400, 500];
|
|
|
|
// Store data with custom IDs
|
|
for (i, &id) in custom_ids.iter().enumerate() {
|
|
let data = format!("Record with custom ID {}", id);
|
|
db.set(OurDBSetArgs { id: Some(id), data: data.as_bytes() })?;
|
|
println!("Stored record {} with custom ID: {}", i+1, id);
|
|
}
|
|
|
|
// Retrieve data by custom IDs
|
|
for &id in &custom_ids {
|
|
let retrieved = db.get(id)?;
|
|
println!("Retrieved ID {}: {}", id, String::from_utf8_lossy(&retrieved));
|
|
}
|
|
|
|
// Update and track history
|
|
let id_to_update = custom_ids[2]; // ID 300
|
|
for i in 1..=3 {
|
|
let updated_data = format!("Updated record {} (version {})", id_to_update, i);
|
|
db.set(OurDBSetArgs { id: Some(id_to_update), data: updated_data.as_bytes() })?;
|
|
println!("Updated ID {} (version {})", id_to_update, i);
|
|
}
|
|
|
|
// Get history for the updated record
|
|
let history = db.get_history(id_to_update, 5)?;
|
|
println!("History for ID {} (most recent first):", id_to_update);
|
|
for (i, entry) in history.iter().enumerate() {
|
|
println!(" Version {}: {}", i, String::from_utf8_lossy(entry));
|
|
}
|
|
|
|
db.close()?;
|
|
println!("Key-value mode example completed");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn incremental_mode_example(base_path: &PathBuf) -> Result<(), ourdb::Error> {
|
|
println!("\n=== Incremental Mode Example ===");
|
|
|
|
let db_path = base_path.join("incremental");
|
|
std::fs::create_dir_all(&db_path)?;
|
|
|
|
// Create a new database with incremental mode
|
|
let config = OurDBConfig {
|
|
path: db_path,
|
|
incremental_mode: true,
|
|
file_size: Some(1024 * 1024), // 1MB for testing
|
|
keysize: Some(3), // 3-byte keys
|
|
};
|
|
|
|
let mut db = OurDB::new(config)?;
|
|
|
|
// In incremental mode, IDs are auto-generated
|
|
let mut assigned_ids = Vec::new();
|
|
|
|
// Store multiple records and collect assigned IDs
|
|
for i in 1..=5 {
|
|
let data = format!("Auto-increment record {}", i);
|
|
let id = db.set(OurDBSetArgs { id: None, data: data.as_bytes() })?;
|
|
assigned_ids.push(id);
|
|
println!("Stored record {} with auto-assigned ID: {}", i, id);
|
|
}
|
|
|
|
// Check next ID
|
|
let next_id = db.get_next_id()?;
|
|
println!("Next ID to be assigned: {}", next_id);
|
|
|
|
// Retrieve all records
|
|
for &id in &assigned_ids {
|
|
let retrieved = db.get(id)?;
|
|
println!("Retrieved ID {}: {}", id, String::from_utf8_lossy(&retrieved));
|
|
}
|
|
|
|
db.close()?;
|
|
println!("Incremental mode example completed");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn performance_benchmark(base_path: &PathBuf) -> Result<(), ourdb::Error> {
|
|
println!("\n=== Performance Benchmark ===");
|
|
|
|
let db_path = base_path.join("benchmark");
|
|
std::fs::create_dir_all(&db_path)?;
|
|
|
|
// Create a new database
|
|
let config = OurDBConfig {
|
|
path: db_path,
|
|
incremental_mode: true,
|
|
file_size: Some(1024 * 1024), // 10MB
|
|
keysize: Some(4), // 4-byte keys
|
|
};
|
|
|
|
let mut db = OurDB::new(config)?;
|
|
|
|
// Number of operations for the benchmark
|
|
let num_operations = 1000;
|
|
let data_size = 100; // bytes per record
|
|
|
|
// Prepare test data
|
|
let test_data = vec![b'A'; data_size];
|
|
|
|
// Benchmark write operations
|
|
println!("Benchmarking {} write operations...", num_operations);
|
|
let start = Instant::now();
|
|
|
|
let mut ids = Vec::with_capacity(num_operations);
|
|
for _ in 0..num_operations {
|
|
let id = db.set(OurDBSetArgs { id: None, data: &test_data })?;
|
|
ids.push(id);
|
|
}
|
|
|
|
let write_duration = start.elapsed();
|
|
let writes_per_second = num_operations as f64 / write_duration.as_secs_f64();
|
|
println!("Write performance: {:.2} ops/sec ({:.2} ms/op)",
|
|
writes_per_second,
|
|
write_duration.as_secs_f64() * 1000.0 / num_operations as f64);
|
|
|
|
// Benchmark read operations
|
|
println!("Benchmarking {} read operations...", num_operations);
|
|
let start = Instant::now();
|
|
|
|
for &id in &ids {
|
|
let _ = db.get(id)?;
|
|
}
|
|
|
|
let read_duration = start.elapsed();
|
|
let reads_per_second = num_operations as f64 / read_duration.as_secs_f64();
|
|
println!("Read performance: {:.2} ops/sec ({:.2} ms/op)",
|
|
reads_per_second,
|
|
read_duration.as_secs_f64() * 1000.0 / num_operations as f64);
|
|
|
|
// Benchmark update operations
|
|
println!("Benchmarking {} update operations...", num_operations);
|
|
let start = Instant::now();
|
|
|
|
for &id in &ids {
|
|
db.set(OurDBSetArgs { id: Some(id), data: &test_data })?;
|
|
}
|
|
|
|
let update_duration = start.elapsed();
|
|
let updates_per_second = num_operations as f64 / update_duration.as_secs_f64();
|
|
println!("Update performance: {:.2} ops/sec ({:.2} ms/op)",
|
|
updates_per_second,
|
|
update_duration.as_secs_f64() * 1000.0 / num_operations as f64);
|
|
|
|
db.close()?;
|
|
println!("Performance benchmark completed");
|
|
|
|
Ok(())
|
|
}
|