From f3fa85bc2b29c16a3bdf50724d96e404b2ba7593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=93=D1=80=D0=B8=D0=B3=D0=BE=D1=80=D0=B8=D0=B9=20=D0=A1?= =?UTF-8?q?=D0=B0=D1=84=D1=80=D0=BE=D0=BD=D0=BE=D0=B2?= Date: Tue, 18 Nov 2025 21:24:55 +0000 Subject: [PATCH] Delete src/db.rs --- src/db.rs | 1294 ----------------------------------------------------- 1 file changed, 1294 deletions(-) delete mode 100644 src/db.rs diff --git a/src/db.rs b/src/db.rs deleted file mode 100644 index bd1c68d..0000000 --- a/src/db.rs +++ /dev/null @@ -1,1294 +0,0 @@ -//[file name]: db.rs - -mod storage { - use std::collections::HashMap; - use std::sync::Arc; - use parking_lot::RwLock; - use serde_json::Value; - use chrono::Utc; - - /// Движок хранения данных с документной моделью - pub struct StorageEngine { - spaces: Arc>>, - path: String, - } - - struct Space { - documents: HashMap, - tuples: HashMap, - } - - struct Document { - value: Value, - created_at: String, - updated_at: String, - } - - struct Tuple { - value: Value, - created_at: String, - updated_at: String, - } - - impl StorageEngine { - pub fn new(path: &str) -> Result { - Ok(Self { - spaces: Arc::new(RwLock::new(HashMap::new())), - path: path.to_string(), - }) - } - - pub fn create_space(&self, name: &str) -> Result<(), String> { - let mut spaces = self.spaces.write(); - if spaces.contains_key(name) { - return Err("Space already exists".to_string()); - } - spaces.insert(name.to_string(), Space { - documents: HashMap::new(), - tuples: HashMap::new(), - }); - Ok(()) - } - - pub fn delete_space(&self, name: &str) -> Result<(), String> { - let mut spaces = self.spaces.write(); - spaces.remove(name) - .map(|_| ()) - .ok_or_else(|| "Space not found".to_string()) - } - - pub fn insert(&self, space: &str, key: &str, value: Value) -> Result<(), String> { - let mut spaces = self.spaces.write(); - let space_obj = spaces.get_mut(space) - .ok_or_else(|| "Space not found".to_string())?; - - if space_obj.documents.contains_key(key) { - return Err("Document already exists".to_string()); - } - - let timestamp = Utc::now().to_rfc3339(); - space_obj.documents.insert(key.to_string(), Document { - value, - created_at: timestamp.clone(), - updated_at: timestamp, - }); - Ok(()) - } - - pub fn get(&self, space: &str, key: &str) -> Result, String> { - let spaces = self.spaces.read(); - match spaces.get(space) { - Some(space_obj) => Ok(space_obj.documents.get(key).map(|doc| { - let mut value = doc.value.clone(); - if let Some(obj) = value.as_object_mut() { - obj.insert("_created_at".to_string(), Value::String(doc.created_at.clone())); - obj.insert("_updated_at".to_string(), Value::String(doc.updated_at.clone())); - } - value - })), - None => Err("Space not found".to_string()), - } - } - - pub fn update(&self, space: &str, key: &str, value: Value) -> Result<(), String> { - let mut spaces = self.spaces.write(); - let space_obj = spaces.get_mut(space) - .ok_or_else(|| "Space not found".to_string())?; - - if let Some(document) = space_obj.documents.get_mut(key) { - document.value = value; - document.updated_at = Utc::now().to_rfc3339(); - Ok(()) - } else { - Err("Document not found".to_string()) - } - } - - pub fn delete(&self, space: &str, key: &str) -> Result<(), String> { - let mut spaces = self.spaces.write(); - let space_obj = spaces.get_mut(space) - .ok_or_else(|| "Space not found".to_string())?; - - space_obj.documents.remove(key) - .map(|_| ()) - .ok_or_else(|| "Document not found".to_string()) - } - - pub fn create_tuple(&self, space: &str, tuple_id: &str, value: Value) -> Result<(), String> { - let mut spaces = self.spaces.write(); - let space_obj = spaces.get_mut(space) - .ok_or_else(|| "Space not found".to_string())?; - - let timestamp = Utc::now().to_rfc3339(); - space_obj.tuples.insert(tuple_id.to_string(), Tuple { - value, - created_at: timestamp.clone(), - updated_at: timestamp, - }); - Ok(()) - } - - pub fn read_tuple(&self, space: &str, tuple_id: &str) -> Result, String> { - let spaces = self.spaces.read(); - match spaces.get(space) { - Some(space_obj) => Ok(space_obj.tuples.get(tuple_id).map(|tuple| { - let mut value = tuple.value.clone(); - if let Some(obj) = value.as_object_mut() { - obj.insert("_created_at".to_string(), Value::String(tuple.created_at.clone())); - obj.insert("_updated_at".to_string(), Value::String(tuple.updated_at.clone())); - } - value - })), - None => Err("Space not found".to_string()), - } - } - - pub fn delete_tuple(&self, space: &str, tuple_id: &str) -> Result<(), String> { - let mut spaces = self.spaces.write(); - let space_obj = spaces.get_mut(space) - .ok_or_else(|| "Space not found".to_string())?; - - space_obj.tuples.remove(tuple_id) - .map(|_| ()) - .ok_or_else(|| "Tuple not found".to_string()) - } - - pub fn get_all_data(&self) -> HashMap> { - let spaces = self.spaces.read(); - let mut result = HashMap::new(); - - for (space_name, space) in spaces.iter() { - let mut space_data = HashMap::new(); - for (key, document) in &space.documents { - let mut value = document.value.clone(); - if let Some(obj) = value.as_object_mut() { - obj.insert("_created_at".to_string(), Value::String(document.created_at.clone())); - obj.insert("_updated_at".to_string(), Value::String(document.updated_at.clone())); - } - space_data.insert(key.clone(), value); - } - result.insert(space_name.clone(), space_data); - } - - result - } - - pub fn restore_from_data(&self, data: HashMap>) -> Result<(), String> { - let mut spaces = self.spaces.write(); - spaces.clear(); - - for (space_name, documents) in data { - let mut space = Space { - documents: HashMap::new(), - tuples: HashMap::new(), - }; - - for (key, value) in documents { - let timestamp = Utc::now().to_rfc3339(); - let created_at = if let Some(obj) = value.as_object() { - obj.get("_created_at") - .and_then(|v| v.as_str()) - .map(|s| s.to_string()) - .unwrap_or_else(|| timestamp.clone()) - } else { - timestamp.clone() - }; - - let updated_at = if let Some(obj) = value.as_object() { - obj.get("_updated_at") - .and_then(|v| v.as_str()) - .map(|s| s.to_string()) - .unwrap_or_else(|| timestamp.clone()) - } else { - timestamp.clone() - }; - - let mut clean_value = value.clone(); - if let Some(obj) = clean_value.as_object_mut() { - obj.remove("_created_at"); - obj.remove("_updated_at"); - } - - space.documents.insert(key, Document { - value: clean_value, - created_at, - updated_at, - }); - } - - spaces.insert(space_name, space); - } - - Ok(()) - } - } -} - -mod wal { - use std::fs::{OpenOptions, File}; - use std::io::{Write, BufWriter}; - use serde_json::Value; - use chrono::Utc; - - /// Write-Ahead Log для обеспечения durability - pub struct WriteAheadLog { - file: BufWriter, - } - - impl WriteAheadLog { - pub fn new(filename: &str) -> Result { - let file = OpenOptions::new() - .create(true) - .append(true) - .open(filename) - .map_err(|e| format!("Failed to open WAL file: {}", e))?; - - Ok(Self { - file: BufWriter::new(file), - }) - } - - pub fn log_operation(&mut self, operation: &str, collection: &str, key: &str, value: &Value) -> Result<(), String> { - let log_entry = LogEntry { - timestamp: Utc::now().to_rfc3339(), - operation: operation.to_string(), - collection: collection.to_string(), - key: key.to_string(), - value: value.clone(), - }; - - let json_str = serde_json::to_string(&log_entry) - .map_err(|e| format!("Failed to serialize log entry: {}", e))?; - - writeln!(self.file, "{}", json_str) - .map_err(|e| format!("Failed to write to WAL: {}", e))?; - - self.file.flush() - .map_err(|e| format!("Failed to flush WAL: {}", e))?; - - Ok(()) - } - - pub fn recover(&mut self) -> Result<(), String> { - Ok(()) - } - } - - #[derive(serde::Serialize, serde::Deserialize)] - struct LogEntry { - timestamp: String, - operation: String, - collection: String, - key: String, - value: Value, - } -} - -mod index { - use std::collections::{HashMap, BTreeMap}; - use parking_lot::RwLock; - use serde_json::Value; - - /// Менеджер индексов для ускорения поиска - pub struct IndexManager { - primary_indexes: RwLock>, - secondary_indexes: RwLock>>, - } - - struct PrimaryIndex { - index: HashMap, - } - - enum SecondaryIndex { - Hash(HashMap>), - BTree(BTreeMap>), - } - - impl IndexManager { - pub fn new() -> Self { - Self { - primary_indexes: RwLock::new(HashMap::new()), - secondary_indexes: RwLock::new(HashMap::new()), - } - } - - pub fn create_primary_index(&self, collection: &str) -> Result<(), String> { - let mut indexes = self.primary_indexes.write(); - if indexes.contains_key(collection) { - return Err("Primary index already exists".to_string()); - } - - indexes.insert(collection.to_string(), PrimaryIndex { - index: HashMap::new(), - }); - Ok(()) - } - - pub fn create_secondary_index(&self, collection: &str, field: &str, index_type: &str) -> Result<(), String> { - let mut indexes = self.secondary_indexes.write(); - let collection_indexes = indexes.entry(collection.to_string()) - .or_insert_with(HashMap::new); - - if collection_indexes.contains_key(field) { - return Err("Secondary index already exists".to_string()); - } - - let index = match index_type { - "hash" => SecondaryIndex::Hash(HashMap::new()), - "btree" => SecondaryIndex::BTree(BTreeMap::new()), - _ => return Err(format!("Unsupported index type: {}", index_type)), - }; - - collection_indexes.insert(field.to_string(), index); - Ok(()) - } - - pub fn drop_primary_index(&self, collection: &str) -> Result<(), String> { - let mut indexes = self.primary_indexes.write(); - indexes.remove(collection) - .map(|_| ()) - .ok_or_else(|| "Primary index not found".to_string()) - } - - pub fn drop_secondary_index(&self, collection: &str, field: &str) -> Result<(), String> { - let mut indexes = self.secondary_indexes.write(); - if let Some(collection_indexes) = indexes.get_mut(collection) { - collection_indexes.remove(field) - .map(|_| ()) - .ok_or_else(|| "Secondary index not found".to_string()) - } else { - Err("Collection not found".to_string()) - } - } - - pub fn search_index(&self, collection: &str, field: &str, value: &str) -> Result, String> { - let indexes = self.secondary_indexes.read(); - if let Some(collection_indexes) = indexes.get(collection) { - if let Some(index) = collection_indexes.get(field) { - match index { - SecondaryIndex::Hash(hash_map) => { - let json_value: serde_json::Value = serde_json::from_str(value) - .map_err(|e| format!("Invalid value: {}", e))?; - Ok(hash_map.get(&json_value) - .cloned() - .unwrap_or_default()) - }, - _ => Ok(vec![]), // Упрощённая реализация для других типов индексов - } - } else { - Err("Index not found".to_string()) - } - } else { - Err("Collection not found".to_string()) - } - } - - pub fn search_primary(&self, collection: &str, key: &str) -> Option { - let indexes = self.primary_indexes.read(); - indexes.get(collection) - .and_then(|index| index.index.get(key).cloned()) - } - } -} - -mod raft { - use std::collections::HashMap; - use parking_lot::RwLock; - - /// Raft консенсус для кластеризации - pub struct RaftCluster { - nodes: RwLock>, - state: RwLock, - current_node_id: String, - } - - struct RaftNode { - url: String, - role: NodeRole, - } - - #[derive(Clone, Debug, PartialEq)] - pub enum NodeRole { - Leader, - Follower, - Candidate, - } - - struct RaftState { - current_term: u64, - voted_for: Option, - log: Vec, - } - - struct LogEntry { - term: u64, - command: String, - } - - impl RaftCluster { - pub async fn new() -> Result { - let node_id = "node_1".to_string(); - let mut nodes = HashMap::new(); - nodes.insert(node_id.clone(), RaftNode { - url: "http://localhost:9080".to_string(), - role: NodeRole::Leader, // По умолчанию первый узел - лидер - }); - - Ok(Self { - nodes: RwLock::new(nodes), - state: RwLock::new(RaftState { - current_term: 0, - voted_for: None, - log: Vec::new(), - }), - current_node_id: node_id, - }) - } - - pub async fn add_node(&self, node_url: String) -> Result<(), String> { - let node_id = format!("node_{}", self.nodes.read().len() + 1); - let mut nodes = self.nodes.write(); - nodes.insert(node_id.clone(), RaftNode { - url: node_url, - role: NodeRole::Follower, - }); - Ok(()) - } - - pub async fn remove_node(&mut self, node_id: &str) -> Result<(), String> { - let mut nodes = self.nodes.write(); - nodes.remove(node_id) - .map(|_| ()) - .ok_or_else(|| "Node not found".to_string()) - } - - pub fn list_nodes(&self) -> Vec<(String, String)> { - let nodes = self.nodes.read(); - nodes.iter() - .map(|(id, node)| { - let role = match node.role { - NodeRole::Leader => "leader", - NodeRole::Follower => "follower", - NodeRole::Candidate => "candidate", - }; - (id.clone(), role.to_string()) - }) - .collect() - } - - pub fn get_cluster_status(&self) -> String { - let nodes = self.nodes.read(); - if nodes.values().any(|node| matches!(node.role, NodeRole::Leader)) { - "cluster_formed".to_string() - } else { - "cluster_not_formed".to_string() - } - } - - /// Получить роль текущего узла - pub fn get_current_node_role(&self) -> NodeRole { - let nodes = self.nodes.read(); - nodes.get(&self.current_node_id) - .map(|node| node.role.clone()) - .unwrap_or(NodeRole::Follower) - } - - /// Получить ID текущего узла - pub fn get_current_node_id(&self) -> String { - self.current_node_id.clone() - } - } -} - -mod acl { - use std::collections::HashMap; - use parking_lot::RwLock; - use serde_json::Value; - - /// Система контроля доступа (ACL) - pub struct AccessControl { - permissions: RwLock>, - } - - #[derive(Clone)] - pub struct UserPermissions { - pub can_read: bool, - pub can_write: bool, - pub can_create: bool, - pub can_delete: bool, - pub allowed_collections: Vec, - } - - impl AccessControl { - pub fn new() -> Self { - Self { - permissions: RwLock::new(HashMap::new()), - } - } - - pub fn add_user(&self, username: &str, permissions: UserPermissions) { - let mut perms = self.permissions.write(); - perms.insert(username.to_string(), permissions); - } - - pub fn can_read(&self, username: &str, collection: &str) -> bool { - let perms = self.permissions.read(); - if let Some(user_perms) = perms.get(username) { - user_perms.can_read && - (user_perms.allowed_collections.is_empty() || - user_perms.allowed_collections.contains(&collection.to_string())) - } else { - false - } - } - - pub fn can_write(&self, username: &str, collection: &str) -> bool { - let perms = self.permissions.read(); - if let Some(user_perms) = perms.get(username) { - user_perms.can_write && - (user_perms.allowed_collections.is_empty() || - user_perms.allowed_collections.contains(&collection.to_string())) - } else { - false - } - } - - pub fn can_create(&self, username: &str, collection: &str) -> bool { - let perms = self.permissions.read(); - if let Some(user_perms) = perms.get(username) { - user_perms.can_create && - (user_perms.allowed_collections.is_empty() || - user_perms.allowed_collections.contains(&collection.to_string())) - } else { - false - } - } - - pub fn can_delete(&self, username: &str, collection: &str) -> bool { - let perms = self.permissions.read(); - if let Some(user_perms) = perms.get(username) { - user_perms.can_delete && - (user_perms.allowed_collections.is_empty() || - user_perms.allowed_collections.contains(&collection.to_string())) - } else { - false - } - } - } - - impl Default for UserPermissions { - fn default() -> Self { - Self { - can_read: true, - can_write: true, - can_create: true, - can_delete: true, - allowed_collections: vec![], - } - } - } -} - -mod transaction { - use std::collections::HashMap; - use parking_lot::RwLock; - use serde_json::Value; - - #[derive(Debug, Clone)] - pub enum TransactionOperation { - Create { collection: String, key: String, value: Value }, - Update { collection: String, key: String, value: Value }, - Delete { collection: String, key: String }, - } - - #[derive(Debug, Clone)] - pub struct Transaction { - pub id: String, - pub operations: Vec, - pub state: TransactionState, - } - - #[derive(Debug, PartialEq, Clone)] - pub enum TransactionState { - Active, - Committed, - RolledBack, - } - - pub struct TransactionManager { - transactions: RwLock>, - } - - impl TransactionManager { - pub fn new() -> Self { - Self { - transactions: RwLock::new(HashMap::new()), - } - } - - pub fn begin_transaction(&self, transaction_id: String) -> Result<(), String> { - let mut transactions = self.transactions.write(); - if transactions.contains_key(&transaction_id) { - return Err("Transaction already exists".to_string()); - } - - transactions.insert(transaction_id.clone(), Transaction { - id: transaction_id, - operations: Vec::new(), - state: TransactionState::Active, - }); - Ok(()) - } - - pub fn add_operation(&self, transaction_id: &str, operation: TransactionOperation) -> Result<(), String> { - let mut transactions = self.transactions.write(); - if let Some(transaction) = transactions.get_mut(transaction_id) { - if transaction.state != TransactionState::Active { - return Err("Transaction is not active".to_string()); - } - transaction.operations.push(operation); - Ok(()) - } else { - Err("Transaction not found".to_string()) - } - } - - pub fn commit_transaction(&self, transaction_id: &str) -> Result, String> { - let mut transactions = self.transactions.write(); - if let Some(transaction) = transactions.get_mut(transaction_id) { - if transaction.state != TransactionState::Active { - return Err("Transaction is not active".to_string()); - } - transaction.state = TransactionState::Committed; - let operations = transaction.operations.clone(); - transactions.remove(transaction_id); - Ok(operations) - } else { - Err("Transaction not found".to_string()) - } - } - - pub fn rollback_transaction(&self, transaction_id: &str) -> Result<(), String> { - let mut transactions = self.transactions.write(); - if let Some(transaction) = transactions.get_mut(transaction_id) { - transaction.state = TransactionState::RolledBack; - transactions.remove(transaction_id); - Ok(()) - } else { - Err("Transaction not found".to_string()) - } - } - - pub fn get_transaction(&self, transaction_id: &str) -> Option { - let transactions = self.transactions.read(); - transactions.get(transaction_id).cloned() - } - } -} - -mod csv_export { - use std::fs::File; - use std::collections::HashMap; - use serde_json::Value; - use csv::Writer; - - pub struct CsvExporter; - - impl CsvExporter { - pub fn export_data(data: &HashMap>, file_path: &str) -> Result<(), String> { - let file = File::create(file_path) - .map_err(|e| format!("Failed to create file: {}", e))?; - - let mut wtr = Writer::from_writer(file); - - for (collection, documents) in data { - for (key, value) in documents { - if let Some(obj) = value.as_object() { - let mut record = vec![collection.clone(), key.clone()]; - - for (field, field_value) in obj { - record.push(field_value.to_string()); - } - - wtr.write_record(&record) - .map_err(|e| format!("Failed to write record: {}", e))?; - } - } - } - - wtr.flush() - .map_err(|e| format!("Failed to flush writer: {}", e))?; - - Ok(()) - } - - pub fn import_data(file_path: &str) -> Result>, String> { - let file = File::open(file_path) - .map_err(|e| format!("Failed to open file: {}", e))?; - - let mut rdr = csv::Reader::from_reader(file); - let mut result = HashMap::new(); - - for record in rdr.records() { - let record = record.map_err(|e| format!("Failed to read record: {}", e))?; - if record.len() >= 3 { - let collection = record[0].to_string(); - let key = record[1].to_string(); - - let mut document = HashMap::new(); - for (i, field) in record.iter().enumerate().skip(2) { - document.insert(format!("field_{}", i - 2), Value::String(field.to_string())); - } - - result.entry(collection) - .or_insert_with(HashMap::new) - .insert(key, Value::Object(serde_json::Map::from_iter(document))); - } - } - - Ok(result) - } - } -} - -mod replication { - use std::collections::HashMap; - use std::sync::Arc; - use parking_lot::RwLock; - use serde_json::Value; - use std::time::Duration; - - /// Мастер-мастер репликация - pub struct MasterMasterReplication { - enabled: bool, - nodes: Vec, - replication_queue: Arc>>, - } - - #[derive(Clone, Debug)] - pub struct ReplicationOperation { - pub operation: String, - pub collection: String, - pub key: String, - pub value: Value, - pub timestamp: u64, - } - - impl MasterMasterReplication { - pub fn new(enabled: bool, nodes: Vec) -> Self { - Self { - enabled, - nodes, - replication_queue: Arc::new(RwLock::new(Vec::new())), - } - } - - pub fn is_enabled(&self) -> bool { - self.enabled - } - - pub fn enable(&mut self) { - self.enabled = true; - } - - pub fn disable(&mut self) { - self.enabled = false; - } - - pub fn add_operation(&self, operation: ReplicationOperation) { - if self.enabled { - let mut queue = self.replication_queue.write(); - queue.push(operation); - } - } - - pub fn get_pending_operations(&self) -> Vec { - let queue = self.replication_queue.read(); - queue.clone() - } - - pub fn clear_operations(&self) { - let mut queue = self.replication_queue.write(); - queue.clear(); - } - - // Убираем async из этой функции, чтобы избежать проблем с Send - pub fn sync_with_nodes(&self) -> Result<(), String> { - if !self.enabled { - return Ok(()); - } - - let operations = self.get_pending_operations(); - if operations.is_empty() { - return Ok(()); - } - - // Упрощённая реализация синхронизации - // В реальной системе здесь был бы HTTP клиент для отправки операций на другие узлы - log::info!("Syncing {} operations with {} nodes", operations.len(), self.nodes.len()); - - // Очищаем очередь после успешной синхронизации - self.clear_operations(); - - Ok(()) - } - } -} - -mod backup { - use std::fs::File; - use std::collections::HashMap; - use serde_json::Value; - use flate2::write::GzEncoder; - use flate2::Compression; - use std::io::Write; - - /// Менеджер бэкапов - pub struct BackupManager; - - impl BackupManager { - pub fn create_backup(data: &HashMap>, backup_path: &str) -> Result<(), String> { - let file = File::create(backup_path) - .map_err(|e| format!("Failed to create backup file: {}", e))?; - - let mut encoder = GzEncoder::new(file, Compression::default()); - let json_data = serde_json::to_string(data) - .map_err(|e| format!("Failed to serialize backup data: {}", e))?; - - encoder.write_all(json_data.as_bytes()) - .map_err(|e| format!("Failed to write backup data: {}", e))?; - - encoder.finish() - .map_err(|e| format!("Failed to finish backup: {}", e))?; - - Ok(()) - } - - pub fn restore_backup(backup_path: &str) -> Result>, String> { - let file = File::open(backup_path) - .map_err(|e| format!("Failed to open backup file: {}", e))?; - - let decoder = flate2::read::GzDecoder::new(file); - let data: HashMap> = serde_json::from_reader(decoder) - .map_err(|e| format!("Failed to deserialize backup data: {}", e))?; - - Ok(data) - } - } -} - -mod procedures { - use std::collections::HashMap; - use std::fs; - use std::path::Path; - use parking_lot::RwLock; - use serde_json::Value; - - /// Менеджер хранимых процедур - pub struct StoredProceduresManager { - procedures: RwLock>, - procedures_path: String, - } - - impl StoredProceduresManager { - pub fn new(procedures_path: &str) -> Result { - let manager = Self { - procedures: RwLock::new(HashMap::new()), - procedures_path: procedures_path.to_string(), - }; - - // Загружаем существующие процедуры при инициализации - manager.load_procedures()?; - - Ok(manager) - } - - pub fn create_procedure(&self, name: &str, code: &str) -> Result<(), String> { - let mut procedures = self.procedures.write(); - - if procedures.contains_key(name) { - return Err(format!("Procedure '{}' already exists", name)); - } - - procedures.insert(name.to_string(), code.to_string()); - - // Сохраняем процедуру в файл - self.save_procedure(name, code)?; - - Ok(()) - } - - pub fn drop_procedure(&self, name: &str) -> Result<(), String> { - let mut procedures = self.procedures.write(); - - if !procedures.contains_key(name) { - return Err(format!("Procedure '{}' not found", name)); - } - - procedures.remove(name); - - // Удаляем файл процедуры - let file_path = format!("{}/{}.lua", self.procedures_path, name); - if let Err(e) = fs::remove_file(file_path) { - log::warn!("Failed to remove procedure file: {}", e); - } - - Ok(()) - } - - pub fn get_procedure(&self, name: &str) -> Option { - let procedures = self.procedures.read(); - procedures.get(name).cloned() - } - - pub fn list_procedures(&self) -> Vec { - let procedures = self.procedures.read(); - procedures.keys().cloned().collect() - } - - fn load_procedures(&self) -> Result<(), String> { - let path = Path::new(&self.procedures_path); - - // Создаем директорию если не существует - if !path.exists() { - fs::create_dir_all(path) - .map_err(|e| format!("Failed to create procedures directory: {}", e))?; - } - - let entries = fs::read_dir(path) - .map_err(|e| format!("Failed to read procedures directory: {}", e))?; - - let mut procedures = self.procedures.write(); - - for entry in entries { - let entry = entry.map_err(|e| format!("Failed to read directory entry: {}", e))?; - let path = entry.path(); - - if path.is_file() && path.extension().map_or(false, |ext| ext == "lua") { - if let Some(file_name) = path.file_stem().and_then(|s| s.to_str()) { - let code = fs::read_to_string(&path) - .map_err(|e| format!("Failed to read procedure file: {}", e))?; - - procedures.insert(file_name.to_string(), code); - } - } - } - - Ok(()) - } - - fn save_procedure(&self, name: &str, code: &str) -> Result<(), String> { - let file_path = format!("{}/{}.lua", self.procedures_path, name); - fs::write(&file_path, code) - .map_err(|e| format!("Failed to save procedure: {}", e))?; - - Ok(()) - } - } -} - -mod encryption { - use md5::{Digest, Md5}; - - /// Менеджер шифрования для СУБД - pub struct EncryptionManager; - - impl EncryptionManager { - pub fn md5_hash(text: &str) -> String { - let mut hasher = Md5::new(); - hasher.update(text.as_bytes()); - let result = hasher.finalize(); - format!("{:x}", result) - } - - pub fn verify_md5(text: &str, hash: &str) -> bool { - Self::md5_hash(text) == hash - } - } -} - -use std::collections::HashMap; -use std::sync::Arc; -use parking_lot::RwLock; -use serde_json::Value; -use crate::config::Config; - -// Re-export всех модулей -pub use self::storage::StorageEngine; -pub use self::wal::WriteAheadLog; -pub use self::index::IndexManager; -pub use self::raft::RaftCluster; -pub use self::acl::AccessControl; -pub use self::transaction::{TransactionManager, TransactionOperation, TransactionState}; -pub use self::csv_export::CsvExporter; -pub use self::replication::{MasterMasterReplication, ReplicationOperation}; -pub use self::backup::BackupManager; -pub use self::procedures::StoredProceduresManager; -pub use self::encryption::EncryptionManager; // Добавлен менеджер шифрования - -/// Основной класс СУБД -#[derive(Clone)] -pub struct FutriixDB { - storage: Arc, - wal: Arc>, - index_manager: Arc, - raft_cluster: Arc, - acl: Arc, - transaction_manager: Arc, - replication: Arc>, - procedures_manager: Arc, - config: Config, -} - -impl FutriixDB { - pub async fn new(config: &Config) -> Result { - // Создаем директорию для данных если не существует - std::fs::create_dir_all(&config.db_path) - .map_err(|e| format!("Failed to create data directory: {}", e))?; - - let storage = Arc::new(StorageEngine::new(&config.db_path)?); - let wal = Arc::new(RwLock::new(WriteAheadLog::new("wal.log")?)); - let index_manager = Arc::new(IndexManager::new()); - let raft_cluster = Arc::new(RaftCluster::new().await?); - let acl = Arc::new(AccessControl::new()); - let transaction_manager = Arc::new(TransactionManager::new()); - - let replication = Arc::new(RwLock::new(MasterMasterReplication::new( - config.master_master_replication, - config.replication_nodes.clone(), - ))); - - let procedures_manager = Arc::new(StoredProceduresManager::new(&config.stored_procedures_path)?); - - Ok(Self { - storage, - wal, - index_manager, - raft_cluster, - acl, - transaction_manager, - replication, - procedures_manager, - config: config.clone(), - }) - } - - // Методы для работы с хранимыми процедурами - pub fn create_procedure(&self, name: &str, code: &str) -> Result<(), String> { - self.procedures_manager.create_procedure(name, code) - } - - pub fn drop_procedure(&self, name: &str) -> Result<(), String> { - self.procedures_manager.drop_procedure(name) - } - - pub fn get_procedure(&self, name: &str) -> Option { - self.procedures_manager.get_procedure(name) - } - - pub fn list_procedures(&self) -> Vec { - self.procedures_manager.list_procedures() - } - - // Методы для работы с бэкапами - pub fn create_backup(&self, backup_path: &str) -> Result<(), String> { - let data = self.storage.get_all_data(); - BackupManager::create_backup(&data, backup_path) - } - - pub fn restore_backup(&self, backup_path: &str) -> Result<(), String> { - let data = BackupManager::restore_backup(backup_path)?; - self.storage.restore_from_data(data) - } - - // Методы для работы с репликацией - pub fn is_replication_enabled(&self) -> bool { - self.replication.read().is_enabled() - } - - pub fn enable_replication(&self) { - self.replication.write().enable(); - } - - pub fn disable_replication(&self) { - self.replication.write().disable(); - } - - // Убираем async и проблемы с Send - pub fn sync_replication(&self) -> Result<(), String> { - self.replication.read().sync_with_nodes() - } - - // Новые методы для работы с шифрованием - pub fn md5_hash(&self, text: &str) -> String { - EncryptionManager::md5_hash(text) - } - - pub fn verify_md5(&self, text: &str, hash: &str) -> bool { - EncryptionManager::verify_md5(text, hash) - } - - // Метод для создания документа с MD5 хешированием пароля - pub fn insert_with_password_hash(&self, space: &str, key: &str, value: Value, password_field: &str) -> Result<(), String> { - let mut value = value; - - if let Some(obj) = value.as_object_mut() { - if let Some(password_value) = obj.get_mut(password_field) { - if let Some(password) = password_value.as_str() { - let hashed_password = self.md5_hash(password); - *password_value = Value::String(hashed_password); - } - } - } - - self.insert(space, key, value) - } - - // Метод для проверки пароля - pub fn verify_password(&self, space: &str, key: &str, password: &str, password_field: &str) -> Result { - match self.get(space, key) { - Ok(Some(value)) => { - if let Some(obj) = value.as_object() { - if let Some(stored_hash) = obj.get(password_field).and_then(|v| v.as_str()) { - Ok(self.verify_md5(password, stored_hash)) - } else { - Ok(false) - } - } else { - Ok(false) - } - } - Ok(None) => Err("Document not found".to_string()), - Err(e) => Err(e), - } - } - - // Остальные методы СУБД остаются без изменений - pub fn create_space(&self, name: &str) -> Result<(), String> { - self.storage.create_space(name) - } - - pub fn delete_space(&self, name: &str) -> Result<(), String> { - self.storage.delete_space(name) - } - - pub fn insert(&self, space: &str, key: &str, value: Value) -> Result<(), String> { - self.storage.insert(space, key, value) - } - - pub fn get(&self, space: &str, key: &str) -> Result, String> { - self.storage.get(space, key) - } - - pub fn update(&self, space: &str, key: &str, value: Value) -> Result<(), String> { - self.storage.update(space, key, value) - } - - pub fn delete(&self, space: &str, key: &str) -> Result<(), String> { - self.storage.delete(space, key) - } - - pub fn create_tuple(&self, space: &str, tuple_id: &str, value: Value) -> Result<(), String> { - self.storage.create_tuple(space, tuple_id, value) - } - - pub fn read_tuple(&self, space: &str, tuple_id: &str) -> Result, String> { - self.storage.read_tuple(space, tuple_id) - } - - pub fn delete_tuple(&self, space: &str, tuple_id: &str) -> Result<(), String> { - self.storage.delete_tuple(space, tuple_id) - } - - pub fn begin_transaction(&self, transaction_id: String) -> Result<(), String> { - self.transaction_manager.begin_transaction(transaction_id) - } - - pub fn add_operation(&self, transaction_id: &str, operation: TransactionOperation) -> Result<(), String> { - self.transaction_manager.add_operation(transaction_id, operation) - } - - pub fn commit_transaction(&self, transaction_id: &str) -> Result, String> { - self.transaction_manager.commit_transaction(transaction_id) - } - - pub fn rollback_transaction(&self, transaction_id: &str) -> Result<(), String> { - self.transaction_manager.rollback_transaction(transaction_id) - } - - pub fn create_primary_index(&self, collection: &str) -> Result<(), String> { - self.index_manager.create_primary_index(collection) - } - - pub fn create_secondary_index(&self, collection: &str, field: &str, index_type: &str) -> Result<(), String> { - self.index_manager.create_secondary_index(collection, field, index_type) - } - - pub fn drop_primary_index(&self, collection: &str) -> Result<(), String> { - self.index_manager.drop_primary_index(collection) - } - - pub fn drop_secondary_index(&self, collection: &str, field: &str) -> Result<(), String> { - self.index_manager.drop_secondary_index(collection, field) - } - - pub fn search_index(&self, collection: &str, field: &str, value: &str) -> Result, String> { - self.index_manager.search_index(collection, field, value) - } - - pub fn add_user(&self, username: &str, permissions: acl::UserPermissions) { - self.acl.add_user(username, permissions); - } - - pub fn can_read(&self, username: &str, collection: &str) -> bool { - self.acl.can_read(username, collection) - } - - pub fn can_write(&self, username: &str, collection: &str) -> bool { - self.acl.can_write(username, collection) - } - - pub fn can_create(&self, username: &str, collection: &str) -> bool { - self.acl.can_create(username, collection) - } - - pub fn can_delete(&self, username: &str, collection: &str) -> bool { - self.acl.can_delete(username, collection) - } - - pub async fn add_cluster_node(&self, node_url: String) -> Result<(), String> { - self.raft_cluster.add_node(node_url).await - } - - pub async fn remove_cluster_node(&self, node_id: &str) -> Result<(), String> { - // Для удаления узла нам нужно &mut self - // В реальной реализации это потребовало бы изменения архитектуры - Err("Node removal not implemented in this version".to_string()) - } - - pub fn list_cluster_nodes(&self) -> Vec<(String, String)> { - self.raft_cluster.list_nodes() - } - - pub fn get_cluster_status(&self) -> String { - self.raft_cluster.get_cluster_status() - } - - pub fn get_current_node_role(&self) -> raft::NodeRole { - self.raft_cluster.get_current_node_role() - } - - pub fn get_current_node_id(&self) -> String { - self.raft_cluster.get_current_node_id() - } - - pub fn export_to_csv(&self, file_path: &str) -> Result<(), String> { - let data = self.storage.get_all_data(); - CsvExporter::export_data(&data, file_path) - } - - pub fn import_from_csv(&self, file_path: &str) -> Result<(), String> { - let data = CsvExporter::import_data(file_path)?; - self.storage.restore_from_data(data) - } -}