use std::sync::{Mutex, MutexGuard};
use rayon::prelude::*;
use crate::{
indexes::{
cashaccount::TxCashAccountRow, headerindex::HeaderRow, heightindex::HeightIndexRow,
inputindex::InputIndexRow, outputindex::OutputIndexRow,
outputtokenindex::OutputTokenIndexRow, scripthashindex::ScriptHashIndexRow,
tokenoutputindex::TokenOutputIndexRow, DBRow,
},
store::{Row, COLUMN_FAMILIES, META_CF},
};
pub struct WriteBatch {
metadata: Mutex<Vec<Row>>,
cashaccount: Mutex<Vec<Row>>,
header: Mutex<Vec<Row>>,
height: Mutex<Vec<Row>>,
input: Mutex<Vec<Row>>,
output: Mutex<Vec<Row>>,
output_token: Mutex<Vec<Row>>,
scripthash: Mutex<Vec<Row>>,
token_output: Mutex<Vec<Row>>,
}
impl WriteBatch {
pub fn new() -> Self {
WriteBatch {
metadata: Default::default(),
cashaccount: Default::default(),
header: Default::default(),
height: Default::default(),
input: Default::default(),
output: Default::default(),
output_token: Default::default(),
scripthash: Default::default(),
token_output: Default::default(),
}
}
pub fn cf_to_vec_tuples<'a>(&'a self) -> Vec<(&'static str, &'a Mutex<Vec<Row>>)> {
let map = vec![
(META_CF, &self.metadata),
(TxCashAccountRow::CF, &self.cashaccount),
(HeaderRow::CF, &self.header),
(HeightIndexRow::CF, &self.height),
(InputIndexRow::CF, &self.input),
(OutputIndexRow::CF, &self.output),
(OutputTokenIndexRow::CF, &self.output_token),
(ScriptHashIndexRow::CF, &self.scripthash),
(TokenOutputIndexRow::CF, &self.token_output),
];
debug_assert!(map.len() == COLUMN_FAMILIES.len());
map
}
pub fn insert<I: IntoParallelIterator<Item = Row>>(&self, cf_name: &str, rows: I) {
let mut rows: Vec<Row> = rows.into_par_iter().collect();
let mut locked = match cf_name {
META_CF => self.metadata.lock().unwrap(),
TxCashAccountRow::CF => self.cashaccount.lock().unwrap(),
HeaderRow::CF => self.header.lock().unwrap(),
HeightIndexRow::CF => self.height.lock().unwrap(),
InputIndexRow::CF => self.input.lock().unwrap(),
OutputIndexRow::CF => self.output.lock().unwrap(),
OutputTokenIndexRow::CF => self.output_token.lock().unwrap(),
ScriptHashIndexRow::CF => self.scripthash.lock().unwrap(),
TokenOutputIndexRow::CF => self.token_output.lock().unwrap(),
_ => todo!("unknown cf family {cf_name}"),
};
locked.append(&mut rows);
}
pub fn len(&self) -> usize {
let locks: Vec<MutexGuard<Vec<Row>>> = self
.cf_to_vec_tuples()
.into_iter()
.map(|(_, column)| column.lock().unwrap())
.collect();
locks.iter().map(|rows| rows.len()).sum()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Default for WriteBatch {
fn default() -> Self {
Self::new()
}
}