mod config;
mod join;
mod parallel;
mod sort;
#[cfg(test)]
mod tests;
use std::sync::{Arc, Mutex};
use crossbeam_deque::{Injector, Steal, Worker};
use vibesql_storage::Row;
pub use config::{global_config, MorselConfig};
pub use join::morsel_parallel_probe_sqlvalue;
pub use parallel::{
morsel_filter, morsel_map, morsel_parallel_filter, morsel_parallel_filter_map,
morsel_parallel_group, morsel_parallel_map, morsel_parallel_reduce,
};
pub use sort::{morsel_parallel_sort, morsel_sort_by};
pub(crate) type MorselResultsOrdered = Arc<Mutex<Vec<(usize, Vec<Row>)>>>;
const MORSEL_DEBUG_ENV: &str = "MORSEL_DEBUG";
pub(crate) fn morsel_debug_enabled() -> bool {
std::env::var(MORSEL_DEBUG_ENV).is_ok()
}
#[derive(Debug, Clone)]
pub struct Morsel {
start_idx: usize,
row_count: usize,
}
impl Morsel {
pub fn new(start_idx: usize, row_count: usize) -> Self {
Self { start_idx, row_count }
}
#[inline]
pub fn start_idx(&self) -> usize {
self.start_idx
}
#[inline]
pub fn row_count(&self) -> usize {
self.row_count
}
#[inline]
pub fn end_idx(&self) -> usize {
self.start_idx + self.row_count
}
#[inline]
pub fn rows<'a>(&self, source: &'a [Row]) -> &'a [Row] {
&source[self.start_idx..self.end_idx()]
}
}
pub(crate) fn create_morsels(total_rows: usize, morsel_size: usize) -> Vec<Morsel> {
let mut morsels = Vec::with_capacity(total_rows.div_ceil(morsel_size));
let mut start = 0;
while start < total_rows {
let count = (total_rows - start).min(morsel_size);
morsels.push(Morsel::new(start, count));
start += count;
}
morsels
}
pub(crate) fn steal_morsel(injector: &Injector<Morsel>, worker: &Worker<Morsel>) -> Option<Morsel> {
worker.pop().or_else(|| {
loop {
match injector.steal() {
Steal::Success(m) => return Some(m),
Steal::Empty => return None,
Steal::Retry => continue,
}
}
})
}