sled backend

This commit is contained in:
2025-08-22 17:20:44 +02:00
parent 9054737e84
commit dd90a49615
6 changed files with 56 additions and 26 deletions

View File

@@ -1,5 +1,4 @@
use crate::{error::DBError, protocol::Protocol, server::Server}; use crate::{error::DBError, protocol::Protocol, server::Server};
use serde::Serialize;
use tokio::time::{timeout, Duration}; use tokio::time::{timeout, Duration};
use futures::future::select_all; use futures::future::select_all;
@@ -1093,26 +1092,23 @@ async fn dbsize_cmd(server: &Server) -> Result<Protocol, DBError> {
} }
} }
#[derive(Serialize)]
struct ServerInfo {
redis_version: String,
encrypted: bool,
selected_db: u64,
}
async fn info_cmd(server: &Server, section: &Option<String>) -> Result<Protocol, DBError> { async fn info_cmd(server: &Server, section: &Option<String>) -> Result<Protocol, DBError> {
let info = ServerInfo { let storage_info = server.current_storage()?.info()?;
redis_version: "7.0.0".to_string(), let mut info_map: std::collections::HashMap<String, String> = storage_info.into_iter().collect();
encrypted: server.current_storage()?.is_encrypted(),
selected_db: server.selected_db, info_map.insert("redis_version".to_string(), "7.0.0".to_string());
}; info_map.insert("selected_db".to_string(), server.selected_db.to_string());
info_map.insert("backend".to_string(), format!("{:?}", server.option.backend));
let mut info_string = String::new(); let mut info_string = String::new();
info_string.push_str(&format!("# Server\n")); info_string.push_str("# Server\n");
info_string.push_str(&format!("redis_version:{}\n", info.redis_version)); info_string.push_str(&format!("redis_version:{}\n", info_map.get("redis_version").unwrap()));
info_string.push_str(&format!("encrypted:{}\n", if info.encrypted { 1 } else { 0 })); info_string.push_str(&format!("backend:{}\n", info_map.get("backend").unwrap()));
info_string.push_str(&format!("# Keyspace\n")); info_string.push_str(&format!("encrypted:{}\n", info_map.get("is_encrypted").unwrap()));
info_string.push_str(&format!("db{}:keys=0,expires=0,avg_ttl=0\n", info.selected_db));
info_string.push_str("# Keyspace\n");
info_string.push_str(&format!("db{}:keys={},expires=0,avg_ttl=0\n", info_map.get("selected_db").unwrap(), info_map.get("db_size").unwrap()));
match section { match section {
Some(s) => { Some(s) => {

View File

@@ -12,10 +12,12 @@ use crate::error::DBError;
use crate::options; use crate::options;
use crate::protocol::Protocol; use crate::protocol::Protocol;
use crate::storage::Storage; use crate::storage::Storage;
use crate::storage_sled::SledStorage;
use crate::storage_trait::StorageBackend;
#[derive(Clone)] #[derive(Clone)]
pub struct Server { pub struct Server {
pub db_cache: std::sync::Arc<std::sync::RwLock<HashMap<u64, Arc<Storage>>>>, pub db_cache: std::sync::Arc<std::sync::RwLock<HashMap<u64, Arc<dyn StorageBackend>>>>,
pub option: options::DBOption, pub option: options::DBOption,
pub client_name: Option<String>, pub client_name: Option<String>,
pub selected_db: u64, // Changed from usize to u64 pub selected_db: u64, // Changed from usize to u64
@@ -52,7 +54,7 @@ impl Server {
} }
} }
pub fn current_storage(&self) -> Result<Arc<Storage>, DBError> { pub fn current_storage(&self) -> Result<Arc<dyn StorageBackend>, DBError> {
let mut cache = self.db_cache.write().unwrap(); let mut cache = self.db_cache.write().unwrap();
if let Some(storage) = cache.get(&self.selected_db) { if let Some(storage) = cache.get(&self.selected_db) {
@@ -73,11 +75,22 @@ impl Server {
println!("Creating new db file: {}", db_file_path.display()); println!("Creating new db file: {}", db_file_path.display());
let storage = Arc::new(Storage::new( let storage: Arc<dyn StorageBackend> = match self.option.backend {
options::BackendType::Redb => {
Arc::new(Storage::new(
db_file_path, db_file_path,
self.should_encrypt_db(self.selected_db), self.should_encrypt_db(self.selected_db),
self.option.encryption_key.as_deref() self.option.encryption_key.as_deref()
)?); )?)
}
options::BackendType::Sled => {
Arc::new(SledStorage::new(
db_file_path,
self.should_encrypt_db(self.selected_db),
self.option.encryption_key.as_deref()
)?)
}
};
cache.insert(self.selected_db, storage.clone()); cache.insert(self.selected_db, storage.clone());
Ok(storage) Ok(storage)

View File

@@ -277,6 +277,10 @@ impl StorageBackend for Storage {
self.is_encrypted() self.is_encrypted()
} }
fn info(&self) -> Result<Vec<(String, String)>, DBError> {
self.info()
}
fn clone_arc(&self) -> Arc<dyn StorageBackend> { fn clone_arc(&self) -> Arc<dyn StorageBackend> {
unimplemented!("Storage cloning not yet implemented for redb backend") unimplemented!("Storage cloning not yet implemented for redb backend")
} }

View File

@@ -208,6 +208,14 @@ impl Storage {
write_txn.commit()?; write_txn.commit()?;
Ok(applied) Ok(applied)
} }
pub fn info(&self) -> Result<Vec<(String, String)>, DBError> {
let dbsize = self.dbsize()?;
Ok(vec![
("db_size".to_string(), dbsize.to_string()),
("is_encrypted".to_string(), self.is_encrypted().to_string()),
])
}
} }
// Utility function for glob pattern matching // Utility function for glob pattern matching

View File

@@ -825,6 +825,14 @@ impl StorageBackend for SledStorage {
self.crypto.is_some() self.crypto.is_some()
} }
fn info(&self) -> Result<Vec<(String, String)>, DBError> {
let dbsize = self.dbsize()?;
Ok(vec![
("db_size".to_string(), dbsize.to_string()),
("is_encrypted".to_string(), self.is_encrypted().to_string()),
])
}
fn clone_arc(&self) -> Arc<dyn StorageBackend> { fn clone_arc(&self) -> Arc<dyn StorageBackend> {
// Note: This is a simplified clone - in production you might want to // Note: This is a simplified clone - in production you might want to
// handle this differently as sled::Db is already Arc internally // handle this differently as sled::Db is already Arc internally

View File

@@ -51,6 +51,7 @@ pub trait StorageBackend: Send + Sync {
// Metadata // Metadata
fn is_encrypted(&self) -> bool; fn is_encrypted(&self) -> bool;
fn info(&self) -> Result<Vec<(String, String)>, DBError>;
// Clone to Arc for sharing // Clone to Arc for sharing
fn clone_arc(&self) -> Arc<dyn StorageBackend>; fn clone_arc(&self) -> Arc<dyn StorageBackend>;