redis_imitate/storage/
memory.rs

1//! # Memory Storage Module
2//! 
3//! Provides in-memory storage implementation with support for:
4//! - String and List data types
5//! - Transaction management with MULTI/EXEC/DISCARD
6//! - Snapshots for persistence
7//! - LRU caching
8//! - Thread-safe concurrent access
9use std::collections::{HashMap, VecDeque};
10use std::sync::Arc;
11use std::fs::File;
12use std::io::{self, BufWriter, BufReader, Write, BufRead};
13use crate::cache::avlcache::AVLCache;
14use std::time::Duration;
15
16/// Represents a single transaction layer with changes to strings and lists
17#[derive(Clone)]
18struct TransactionLayer {
19    strings: HashMap<String, Option<String>>,
20    lists: HashMap<String, Option<VecDeque<String>>>,
21}
22
23/// Main storage engine implementing Redis-like functionality
24///
25/// Provides thread-safe storage with transaction support and caching.
26/// All keys are case-insensitive and stored in lowercase.
27pub struct MemoryStorage {
28    strings: Arc<HashMap<String, String>>,
29    lists: Arc<HashMap<String, VecDeque<String>>>,
30    transaction_stack: Vec<TransactionLayer>,
31    cache: AVLCache<String,String>,
32}
33
34impl MemoryStorage {
35    /// Creates a new empty storage instance with default cache settings
36    pub fn new() -> Self {
37        MemoryStorage {
38            strings: Arc::new(HashMap::new()),
39            lists: Arc::new(HashMap::new()),
40            transaction_stack: Vec::new(),
41            cache: AVLCache::new(1000, Duration::from_secs(300)),
42        }
43    }
44
45   /// Saves the current storage state to a file
46   ///
47   /// # Arguments
48   ///
49   /// * `path` - Path to save the snapshot file
50    pub fn save_snapshot(&self, path: &str) -> io::Result<()> {
51        let file = File::create(path)?;
52        let mut writer = BufWriter::new(file);
53
54        for (key, value) in self.strings.iter() {
55            writeln!(writer, "STRING {} {}", key, value)?;
56        }
57
58        for (key, list) in self.lists.iter() {
59            write!(writer, "LIST {} {}", key, list.len())?;
60            for item in list {
61                write!(writer, " {}", item)?;
62            }
63            writeln!(writer)?;
64        }
65
66        Ok(())
67    }
68
69   /// Loads storage state from a snapshot file
70   ///
71   /// # Arguments
72   ///
73   /// * `path` - Path to the snapshot file to load
74    pub fn load_snapshot(&mut self, path: &str) -> io::Result<()> {
75        let file = File::open(path)?;
76        let reader = BufReader::new(file);
77        let mut new_strings = HashMap::new();
78        let mut new_lists = HashMap::new();
79
80        for line in reader.lines() {
81            let line = line?;
82            let parts: Vec<&str> = line.split_whitespace().collect();
83            if parts.is_empty() {
84                continue;
85            }
86
87            match parts[0] {
88                "STRING" => {
89                    if parts.len() >= 3 {
90                        new_strings.insert(parts[1].to_string(), parts[2].to_string());
91                    }
92                }
93                "LIST" => {
94                    if parts.len() >= 3 {
95                        let mut list = VecDeque::new();
96                        for item in &parts[3..] {
97                            list.push_back(item.to_string());
98                        }
99                        new_lists.insert(parts[1].to_string(), list);
100                    }
101                }
102                _ => {}
103            }
104        }
105
106        self.strings = Arc::new(new_strings);
107        self.lists = Arc::new(new_lists);
108        Ok(())
109    }
110
111   /// Starts a new transaction
112   ///
113   /// Creates a new transaction layer that will track changes until committed or rolled back.
114    pub fn start_transaction(&mut self) {
115        self.transaction_stack.push(TransactionLayer {
116            strings: HashMap::new(),
117            lists: HashMap::new(),
118        });
119    }
120
121   /// Commits the current transaction
122   ///
123   /// # Returns
124   ///
125   /// * `Ok(Vec<String>)` - Results of operations in the transaction
126   /// * `Err(String)` - Error message if no transaction is active
127    pub fn commit_transaction(&mut self) -> Result<Vec<String>, String> {
128        if self.transaction_stack.is_empty() {
129            return Err("No active transaction to commit".to_string());
130        }
131    
132        let committed_layer = self.transaction_stack.pop().unwrap();
133        let mut results = Vec::new();
134    
135        if self.transaction_stack.is_empty() {
136            // This is the outermost transaction, apply changes to main storage
137            let mut new_strings = (*self.strings).clone();
138            for (key, value_opt) in committed_layer.strings {
139                match value_opt {
140                    Some(value) => { 
141                        new_strings.insert(key, value.clone()); 
142                        results.push("OK".to_string());
143                    }
144                    None => { 
145                        new_strings.remove(&key); 
146                        results.push("OK".to_string());
147                    }
148                }
149            }
150            self.strings = Arc::new(new_strings);
151    
152            let mut new_lists = (*self.lists).clone();
153            for (key, value_opt) in committed_layer.lists {
154                match value_opt {
155                    Some(value) => { 
156                        new_lists.insert(key, value.clone()); 
157                        results.push(value.len().to_string());
158                    }
159                    None => { 
160                        new_lists.remove(&key); 
161                        results.push("OK".to_string());
162                    }
163                }
164            }
165            self.lists = Arc::new(new_lists);
166        } else {
167            // This is a nested transaction, merge changes into the parent transaction
168            let parent_layer = self.transaction_stack.last_mut().unwrap();
169            for (key, value_opt) in committed_layer.strings {
170                parent_layer.strings.insert(key, value_opt);
171                results.push("QUEUED".to_string());
172            }
173            for (key, value_opt) in committed_layer.lists {
174                parent_layer.lists.insert(key, value_opt);
175                results.push("QUEUED".to_string());
176            }
177        }
178        
179        self.cache.clear();
180        Ok(results)
181    }
182
183   /// Rolls back the current transaction
184   ///
185   /// # Returns
186   ///
187   /// * `Ok(())` - Transaction successfully rolled back
188   /// * `Err(String)` - Error message if no transaction is active
189    pub fn rollback_transaction(&mut self) -> Result<(), String> {
190        if self.transaction_stack.is_empty() {
191            return Err("No active transaction to rollback".to_string());
192        }
193        self.transaction_stack.pop();
194        self.cache.clear();
195        Ok(())
196    }
197
198    /// Sets a key-value pair in the storage
199    ///
200    /// If a transaction is active, the change is recorded in the current transaction layer.
201    /// Otherwise, it's applied directly to the main storage. The value is also cached.
202    ///
203    /// # Arguments
204    ///
205    /// * `key` - The key (case-insensitive)
206    /// * `value` - The value to store
207    pub fn set(&mut self, key: String, value: String) {
208        let key = key.to_lowercase();
209        if let Some(layer) = self.transaction_stack.last_mut() {
210            layer.strings.insert(key.clone(), Some(value.clone()));
211        } else {
212            Arc::make_mut(&mut self.strings).insert(key.clone(), value.clone());
213        }
214        self.cache.put(key, value);
215    }
216
217    /// Retrieves a value by its key
218    ///
219    /// Checks the cache first, then active transactions from newest to oldest,
220    /// finally falling back to main storage. Found values are cached for future access.
221    ///
222    /// # Arguments
223    ///
224    /// * `key` - The key to look up (case-insensitive)
225    ///
226    /// # Returns
227    ///
228    /// * `Some(String)` - The value if found
229    /// * `None` - If the key doesn't exist
230    pub fn get(&mut self, key: &str) -> Option<String> {
231        let key = key.to_lowercase();
232        
233        if let Some(value) = self.cache.get(&key) {
234            return Some(value);
235        }
236    
237        let result = self.transaction_stack.iter().rev()
238            .find_map(|layer| layer.strings.get(&key).cloned().flatten())
239            .or_else(|| self.strings.get(&key).cloned());
240    
241        if let Some(value) = result.as_ref() {
242            self.cache.put(key.clone(), value.clone());
243        }
244    
245        result
246    }
247
248    /// Deletes a key-value pair from storage
249    ///
250    /// In a transaction, marks the key for deletion.
251    /// Otherwise, removes it from main storage immediately.
252    /// Also removes the key from cache if it existed.
253    ///
254    /// # Arguments
255    ///
256    /// * `key` - The key to delete (case-insensitive)
257    ///
258    /// # Returns
259    ///
260    /// `true` if the key existed and was marked for deletion or removed
261    pub fn del(&mut self, key: &str) -> bool {
262        let key = key.to_lowercase();
263        let result = if let Some(layer) = self.transaction_stack.last_mut() {
264            layer.strings.insert(key.to_string(), None);
265            layer.lists.insert(key.to_string(), None);
266            true
267        } else {
268            Arc::make_mut(&mut self.strings).remove(&key).is_some() ||
269            Arc::make_mut(&mut self.lists).remove(&key).is_some()
270        };
271        if result {
272            self.cache.remove(&key);
273        }
274
275        result
276    }
277
278    /// Increments the numeric value stored at the given key
279    ///
280    /// If the key doesn't exist, it's initialized with "0" before incrementing.
281    /// Non-numeric values are treated as 0.
282    ///
283    /// # Arguments
284    ///
285    /// * `key` - The key storing the numeric value (case-insensitive)
286    ///
287    /// # Returns
288    ///
289    /// The new value after incrementing
290    pub fn incr(&mut self, key: &str) -> i64 {
291        let key = key.to_lowercase();
292        let value = self.get_or_insert_string(&key, "0".to_string());
293        let mut num: i64 = value.parse().unwrap_or(0);
294        num += 1;
295        *value = num.to_string();
296        num
297    }
298
299    /// Decrements the numeric value stored at the given key
300    ///
301    /// If the key doesn't exist, it's initialized with "0" before decrementing.
302    /// Non-numeric values are treated as 0.
303    ///
304    /// # Arguments
305    ///
306    /// * `key` - The key storing the numeric value (case-insensitive)
307    ///
308    /// # Returns
309    ///
310    /// The new value after decrementing
311    pub fn decr(&mut self, key: &str) -> i64 {
312        let key = key.to_lowercase();
313        let value = self.get_or_insert_string(&key, "0".to_string());
314        let mut num: i64 = value.parse().unwrap_or(0);
315        num -= 1;
316        *value = num.to_string();
317        num
318    }
319    
320    /// Pushes a value to the front of a list
321    ///
322    /// Creates the list if it doesn't exist.
323    ///
324    /// # Arguments
325    ///
326    /// * `key` - The list's key (case-insensitive)
327    /// * `value` - The value to push
328    ///
329    /// # Returns
330    ///
331    /// The new length of the list
332    pub fn lpush(&mut self, key: &str, value: String) -> usize {
333        let key = key.to_lowercase();
334        let list = self.get_or_insert_list(&key);
335        list.push_front(value);
336        list.len()
337    }
338    
339    /// Pushes a value to the end of a list
340    ///
341    /// Creates the list if it doesn't exist.
342    ///
343    /// # Arguments
344    ///
345    /// * `key` - The list's key (case-insensitive)
346    /// * `value` - The value to push
347    ///
348    /// # Returns
349    ///
350    /// The new length of the list
351    pub fn rpush(&mut self, key: &str, value: String) -> usize {
352        let key = key.to_lowercase();
353        let list = self.get_or_insert_list(&key);
354        list.push_back(value);
355        list.len()
356    }
357
358    /// Removes and returns the first element from a list
359    ///
360    /// # Arguments
361    ///
362    /// * `key` - The list's key (case-insensitive)
363    ///
364    /// # Returns
365    ///
366    /// * `Some(String)` - The removed value
367    /// * `None` - If the list is empty or doesn't exist
368    pub fn lpop(&mut self, key: &str) -> Option<String> {
369        let key = key.to_lowercase();
370        self.get_or_insert_list(&key).pop_front()
371    }
372
373    /// Removes and returns the last element from a list
374    ///
375    /// # Arguments
376    ///
377    /// * `key` - The list's key (case-insensitive)
378    ///
379    /// # Returns
380    ///
381    /// * `Some(String)` - The removed value
382    /// * `None` - If the list is empty or doesn't exist
383    pub fn rpop(&mut self, key: &str) -> Option<String> {
384        let key = key.to_lowercase();
385        self.get_or_insert_list(&key).pop_back()
386    }
387
388    /// Returns the length of a list
389    ///
390    /// If in a transaction, returns the length from the most recent transaction layer
391    /// that has the list. Otherwise, returns the length from main storage.
392    ///
393    /// # Arguments
394    ///
395    /// * `key` - The list's key (case-insensitive)
396    ///
397    /// # Returns
398    ///
399    /// The length of the list, or 0 if it doesn't exist
400    pub fn llen(&self, key: &str) -> usize {
401        let key = key.to_lowercase();
402        for layer in self.transaction_stack.iter().rev() {
403            if let Some(Some(list)) = layer.lists.get(&key) {
404                return list.len();
405            }
406        }
407        self.lists.get(&key).map_or(0, |list| list.len())
408    }
409
410    /// Helper method to get or insert a string value
411    ///
412    /// Returns a mutable reference to the string value, creating it if necessary
413    fn get_or_insert_string(&mut self, key: &str, default: String) -> &mut String {
414        let key = key.to_lowercase();
415        if let Some(layer) = self.transaction_stack.last_mut() {
416            layer.strings.entry(key.to_string())
417                .or_insert_with(|| self.strings.get(&key).cloned())
418                .get_or_insert(default)
419        } else {
420            Arc::make_mut(&mut self.strings)
421                .entry(key.to_string())
422                .or_insert(default)
423        }
424    }
425
426   /// Helper method to get or insert a list
427   ///
428   /// Returns a mutable reference to the list, creating it if necessary
429    fn get_or_insert_list(&mut self, key: &str) -> &mut VecDeque<String> {
430        let key = key.to_lowercase();
431        if let Some(layer) = self.transaction_stack.last_mut() {
432            layer.lists.entry(key.to_string())
433                .or_insert_with(|| self.lists.get(&key).cloned())
434                .get_or_insert_with(VecDeque::new)
435        } else {
436            Arc::make_mut(&mut self.lists)
437                .entry(key.to_string())
438                .or_insert_with(VecDeque::new)
439        }
440    }
441}