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
8pub struct WriteAheadLog {
11 file: Arc<Mutex<BufWriter<File>>>,
12 raw_file: Arc<Mutex<File>>, #[allow(dead_code)]
14 path: PathBuf, }
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 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 #[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 #[inline]
48 pub fn sync(&self) -> Result<()> {
49 let mut writer = self.file.lock();
50 writer.flush()?;
51
52 let raw = self.raw_file.lock();
54 raw.sync_data()?; Ok(())
56 }
57
58 #[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