use crate::{Record, Result};
use std::sync::{Arc, Mutex};
pub type Lsn = u64;
#[derive(Clone)]
pub struct MemoryWal {
inner: Arc<Mutex<MemoryWalInner>>,
}
struct MemoryWalInner {
records: Vec<(Lsn, Record)>,
next_lsn: Lsn,
}
impl MemoryWal {
pub fn create() -> Result<Self> {
Ok(Self {
inner: Arc::new(Mutex::new(MemoryWalInner {
records: Vec::new(),
next_lsn: 1,
})),
})
}
pub fn open() -> Result<Self> {
Self::create()
}
pub fn append(&self, record: Record) -> Result<Lsn> {
let mut inner = self.inner.lock().unwrap();
let lsn = inner.next_lsn;
inner.next_lsn += 1;
inner.records.push((lsn, record));
Ok(lsn)
}
pub fn flush(&self) -> Result<()> {
Ok(())
}
pub fn read_all(&self) -> Result<Vec<(Lsn, Record)>> {
let inner = self.inner.lock().unwrap();
Ok(inner.records.clone())
}
pub fn next_lsn(&self) -> Lsn {
let inner = self.inner.lock().unwrap();
inner.next_lsn
}
pub fn clear(&self) {
let mut inner = self.inner.lock().unwrap();
inner.records.clear();
}
pub fn len(&self) -> usize {
let inner = self.inner.lock().unwrap();
inner.records.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Key, Value};
use std::collections::HashMap;
fn create_test_record(pk: &[u8], seq: u64) -> Record {
let mut item = HashMap::new();
item.insert("test".to_string(), Value::string("value"));
Record::put(Key::new(pk.to_vec()), item, seq)
}
#[test]
fn test_memory_wal_create() {
let wal = MemoryWal::create().unwrap();
assert_eq!(wal.next_lsn(), 1);
assert!(wal.is_empty());
}
#[test]
fn test_memory_wal_append() {
let wal = MemoryWal::create().unwrap();
let record = create_test_record(b"key1", 1);
let lsn = wal.append(record).unwrap();
assert_eq!(lsn, 1);
assert_eq!(wal.next_lsn(), 2);
assert_eq!(wal.len(), 1);
}
#[test]
fn test_memory_wal_read_all() {
let wal = MemoryWal::create().unwrap();
let record1 = create_test_record(b"key1", 1);
let record2 = create_test_record(b"key2", 2);
wal.append(record1.clone()).unwrap();
wal.append(record2.clone()).unwrap();
let records = wal.read_all().unwrap();
assert_eq!(records.len(), 2);
assert_eq!(records[0].0, 1);
assert_eq!(records[1].0, 2);
}
#[test]
fn test_memory_wal_flush_noop() {
let wal = MemoryWal::create().unwrap();
let record = create_test_record(b"key1", 1);
wal.append(record).unwrap();
wal.flush().unwrap();
assert_eq!(wal.len(), 1);
}
#[test]
fn test_memory_wal_clear() {
let wal = MemoryWal::create().unwrap();
wal.append(create_test_record(b"key1", 1)).unwrap();
wal.append(create_test_record(b"key2", 2)).unwrap();
assert_eq!(wal.len(), 2);
wal.clear();
assert!(wal.is_empty());
assert_eq!(wal.next_lsn(), 3); }
#[test]
fn test_memory_wal_clone() {
let wal = MemoryWal::create().unwrap();
wal.append(create_test_record(b"key1", 1)).unwrap();
let wal2 = wal.clone();
assert_eq!(wal2.len(), 1);
wal2.append(create_test_record(b"key2", 2)).unwrap();
assert_eq!(wal.len(), 2);
}
}