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}