vectx_storage/
wal.rs

1use anyhow::Result;
2use std::fs::{File, OpenOptions};
3use std::io::{BufWriter, Write};
4use std::path::{Path, PathBuf};
5use std::sync::Arc;
6use parking_lot::Mutex;
7
8/// Write-Ahead Log for durability
9/// Inspired by Redis AOF (Append Only File) patterns
10pub struct WriteAheadLog {
11    file: Arc<Mutex<BufWriter<File>>>,
12    raw_file: Arc<Mutex<File>>,  // For fsync operations
13    #[allow(dead_code)]
14    path: PathBuf,  // Stored for potential future use (e.g., log rotation)
15}
16
17impl WriteAheadLog {
18    pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
19        let path = path.as_ref().to_path_buf();
20        let file = OpenOptions::new()
21            .create(true)
22            .append(true)
23            .open(&path)?;
24        
25        // Clone the file for fsync operations (Redis pattern)
26        let raw_file = file.try_clone()?;
27
28        Ok(Self {
29            file: Arc::new(Mutex::new(BufWriter::new(file))),
30            raw_file: Arc::new(Mutex::new(raw_file)),
31            path,
32        })
33    }
34
35    /// Append data to the WAL
36    #[inline]
37    pub fn append(&self, data: &[u8]) -> Result<()> {
38        let mut writer = self.file.lock();
39        writer.write_all(data)?;
40        writer.write_all(b"\n")?;
41        writer.flush()?;
42        Ok(())
43    }
44
45    /// Sync WAL to disk (like Redis fsync)
46    /// Uses sync_data() which is equivalent to fdatasync on Unix
47    #[inline]
48    pub fn sync(&self) -> Result<()> {
49        let mut writer = self.file.lock();
50        writer.flush()?;
51        
52        // Ensure data is persisted to disk (Redis-style durability)
53        let raw = self.raw_file.lock();
54        raw.sync_data()?;  // fdatasync equivalent - faster than sync_all()
55        Ok(())
56    }
57
58    /// Full sync including metadata (for critical operations)
59    #[inline]
60    pub fn sync_all(&self) -> Result<()> {
61        let mut writer = self.file.lock();
62        writer.flush()?;
63        
64        let raw = self.raw_file.lock();
65        raw.sync_all()?;
66        Ok(())
67    }
68}
69