2020-11-04 12:38:35 +00:00
|
|
|
use anyhow::{anyhow, Result};
|
2021-03-24 14:20:20 +00:00
|
|
|
use std::collections::BTreeSet;
|
2020-11-04 12:38:35 +00:00
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
|
|
use crate::checksum;
|
|
|
|
use crate::io_engine::*;
|
|
|
|
use crate::pdata::space_map::*;
|
|
|
|
|
|
|
|
//------------------------------------------
|
|
|
|
|
2020-12-09 13:22:32 +00:00
|
|
|
#[derive(Clone)]
|
2020-11-04 12:38:35 +00:00
|
|
|
pub struct WriteBatcher {
|
2020-12-09 13:22:32 +00:00
|
|
|
pub engine: Arc<dyn IoEngine + Send + Sync>,
|
2021-03-24 14:20:20 +00:00
|
|
|
|
|
|
|
// FIXME: this doesn't need to be in a mutex
|
2020-12-09 13:22:32 +00:00
|
|
|
pub sm: Arc<Mutex<dyn SpaceMap>>,
|
2020-11-04 12:38:35 +00:00
|
|
|
|
|
|
|
batch_size: usize,
|
|
|
|
queue: Vec<Block>,
|
2021-03-24 14:20:20 +00:00
|
|
|
allocations: BTreeSet<u64>,
|
2020-11-04 12:38:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl WriteBatcher {
|
|
|
|
pub fn new(
|
|
|
|
engine: Arc<dyn IoEngine + Send + Sync>,
|
|
|
|
sm: Arc<Mutex<dyn SpaceMap>>,
|
|
|
|
batch_size: usize,
|
|
|
|
) -> WriteBatcher {
|
|
|
|
WriteBatcher {
|
|
|
|
engine,
|
|
|
|
sm,
|
|
|
|
batch_size,
|
|
|
|
queue: Vec::with_capacity(batch_size),
|
2021-03-24 14:20:20 +00:00
|
|
|
allocations: BTreeSet::new(),
|
2020-11-04 12:38:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 14:20:20 +00:00
|
|
|
pub fn alloc(&mut self) -> Result<Block> {
|
2020-11-04 12:38:35 +00:00
|
|
|
let mut sm = self.sm.lock().unwrap();
|
|
|
|
let b = sm.alloc()?;
|
|
|
|
|
|
|
|
if b.is_none() {
|
|
|
|
return Err(anyhow!("out of metadata space"));
|
|
|
|
}
|
|
|
|
|
2021-05-26 01:41:37 +08:00
|
|
|
self.allocations.insert(b.unwrap());
|
2021-03-24 14:20:20 +00:00
|
|
|
Ok(Block::new(b.unwrap()))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_allocations(&mut self) -> BTreeSet<u64> {
|
|
|
|
let mut tmp = BTreeSet::new();
|
|
|
|
std::mem::swap(&mut tmp, &mut self.allocations);
|
|
|
|
tmp
|
2020-11-04 12:38:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write(&mut self, b: Block, kind: checksum::BT) -> Result<()> {
|
|
|
|
checksum::write_checksum(&mut b.get_data(), kind)?;
|
|
|
|
|
|
|
|
if self.queue.len() == self.batch_size {
|
2021-03-24 14:20:20 +00:00
|
|
|
let mut tmp = Vec::new();
|
|
|
|
std::mem::swap(&mut tmp, &mut self.queue);
|
|
|
|
self.flush_(tmp)?;
|
2020-11-04 12:38:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.queue.push(b);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-05-02 23:51:56 +08:00
|
|
|
pub fn read(&mut self, blocknr: u64) -> Result<Block> {
|
|
|
|
for b in self.queue.iter().rev() {
|
|
|
|
if b.loc == blocknr {
|
|
|
|
let r = Block::new(b.loc);
|
|
|
|
r.get_data().copy_from_slice(b.get_data());
|
|
|
|
return Ok(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-04 16:10:20 +08:00
|
|
|
self.engine
|
|
|
|
.read(blocknr)
|
|
|
|
.map_err(|_| anyhow!("read block error"))
|
2021-05-02 23:51:56 +08:00
|
|
|
}
|
|
|
|
|
2021-03-24 14:20:20 +00:00
|
|
|
pub fn flush_(&mut self, queue: Vec<Block>) -> Result<()> {
|
|
|
|
self.engine.write_many(&queue)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-11-04 12:38:35 +00:00
|
|
|
pub fn flush(&mut self) -> Result<()> {
|
2021-03-24 14:20:20 +00:00
|
|
|
let mut tmp = Vec::new();
|
|
|
|
std::mem::swap(&mut tmp, &mut self.queue);
|
|
|
|
self.flush_(tmp)?;
|
2020-11-04 12:38:35 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------
|