2024-01-25 12:07:53 +08:00
|
|
|
use std::fs::{File, OpenOptions};
|
|
|
|
|
use std::io::{Read, Write};
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
2024-01-25 21:53:47 +08:00
|
|
|
use anyhow::{bail, Context, Result};
|
|
|
|
|
use bytes::{Buf, BufMut};
|
2024-01-25 12:07:53 +08:00
|
|
|
use parking_lot::{Mutex, MutexGuard};
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
|
|
use crate::compact::CompactionTask;
|
|
|
|
|
|
|
|
|
|
pub struct Manifest {
|
|
|
|
|
file: Arc<Mutex<File>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
|
pub enum ManifestRecord {
|
|
|
|
|
Flush(usize),
|
|
|
|
|
NewMemtable(usize),
|
|
|
|
|
Compaction(CompactionTask, Vec<usize>),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Manifest {
|
|
|
|
|
pub fn create(path: impl AsRef<Path>) -> Result<Self> {
|
|
|
|
|
Ok(Self {
|
|
|
|
|
file: Arc::new(Mutex::new(
|
|
|
|
|
OpenOptions::new()
|
|
|
|
|
.read(true)
|
|
|
|
|
.create_new(true)
|
|
|
|
|
.write(true)
|
|
|
|
|
.open(path)
|
|
|
|
|
.context("failed to create manifest")?,
|
|
|
|
|
)),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn recover(path: impl AsRef<Path>) -> Result<(Self, Vec<ManifestRecord>)> {
|
|
|
|
|
let mut file = OpenOptions::new()
|
|
|
|
|
.read(true)
|
|
|
|
|
.append(true)
|
|
|
|
|
.open(path)
|
|
|
|
|
.context("failed to recover manifest")?;
|
|
|
|
|
let mut buf = Vec::new();
|
|
|
|
|
file.read_to_end(&mut buf)?;
|
2024-01-25 21:53:47 +08:00
|
|
|
let mut buf_ptr = buf.as_slice();
|
2024-01-25 12:07:53 +08:00
|
|
|
let mut records = Vec::new();
|
2024-01-25 21:53:47 +08:00
|
|
|
while buf_ptr.has_remaining() {
|
|
|
|
|
let len = buf_ptr.get_u64();
|
|
|
|
|
let slice = &buf_ptr[..len as usize];
|
|
|
|
|
let json = serde_json::from_slice::<ManifestRecord>(slice)?;
|
|
|
|
|
buf_ptr.advance(len as usize);
|
|
|
|
|
let checksum = buf_ptr.get_u32();
|
|
|
|
|
if checksum != crc32fast::hash(slice) {
|
|
|
|
|
bail!("checksum mismatched!");
|
|
|
|
|
}
|
|
|
|
|
records.push(json);
|
2024-01-25 12:07:53 +08:00
|
|
|
}
|
|
|
|
|
Ok((
|
|
|
|
|
Self {
|
|
|
|
|
file: Arc::new(Mutex::new(file)),
|
|
|
|
|
},
|
|
|
|
|
records,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_record(
|
|
|
|
|
&self,
|
|
|
|
|
_state_lock_observer: &MutexGuard<()>,
|
|
|
|
|
record: ManifestRecord,
|
|
|
|
|
) -> Result<()> {
|
|
|
|
|
self.add_record_when_init(record)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn add_record_when_init(&self, record: ManifestRecord) -> Result<()> {
|
|
|
|
|
let mut file = self.file.lock();
|
2024-01-25 21:53:47 +08:00
|
|
|
let mut buf = serde_json::to_vec(&record)?;
|
|
|
|
|
let hash = crc32fast::hash(&buf);
|
|
|
|
|
file.write_all(&(buf.len() as u64).to_be_bytes())?;
|
|
|
|
|
buf.put_u32(hash);
|
2024-01-25 12:07:53 +08:00
|
|
|
file.write_all(&buf)?;
|
|
|
|
|
file.sync_all()?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|