use crate::KeyRing;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::sync::{Arc, Mutex};
use crate::error::ReadError;
use crate::record::Record;
use super::iter::RecordIter;
use super::{iter_for_segment, ManifestEntry, SegmentManifest};
struct ShardScanner {
key: Option<Arc<KeyRing>>,
from_id: u64,
to_id: u64,
segments: Vec<ManifestEntry>,
seg_idx: usize,
cur: Option<RecordIter>,
}
impl ShardScanner {
fn new(
manifest: Arc<Mutex<SegmentManifest>>,
key: Option<Arc<KeyRing>>,
from_id: u64,
to_id: u64,
) -> Result<Self, ReadError> {
let segments = manifest.lock().unwrap().segments_from(from_id)?;
Ok(Self {
key,
from_id,
to_id,
segments,
seg_idx: 0,
cur: None,
})
}
fn load_next_segment(&mut self) -> bool {
while self.seg_idx < self.segments.len() {
let entry = &self.segments[self.seg_idx];
self.seg_idx += 1;
if entry.base_sequence() >= self.to_id {
self.cur = None;
return false;
}
match iter_for_segment(entry, self.from_id, self.to_id, self.key.clone()) {
Ok(it) => {
self.cur = Some(it);
return true;
}
Err(_) => continue, }
}
self.cur = None;
false
}
}
impl Iterator for ShardScanner {
type Item = Result<Record, ReadError>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(it) = &mut self.cur {
if let Some(r) = it.next() {
return Some(r);
}
}
if !self.load_next_segment() {
return None;
}
}
}
}
struct MergeIter {
scanners: Vec<ShardScanner>,
peeked: Vec<Option<Record>>,
pending_err: Option<ReadError>,
heap: BinaryHeap<Reverse<(u64, usize)>>,
}
impl MergeIter {
fn new(scanners: Vec<ShardScanner>) -> Result<Self, ReadError> {
let n = scanners.len();
let mut merge = Self {
scanners,
peeked: vec![None; n],
pending_err: None,
heap: BinaryHeap::with_capacity(n),
};
for i in 0..n {
merge.refill(i);
}
Ok(merge)
}
fn refill(&mut self, i: usize) {
match self.scanners[i].next() {
Some(Ok(r)) => {
let gid = r.id.sequence;
self.peeked[i] = Some(r);
self.heap.push(Reverse((gid, i)));
}
Some(Err(e)) => {
if self.pending_err.is_none() {
self.pending_err = Some(e);
}
self.peeked[i] = None;
}
None => {
self.peeked[i] = None;
}
}
}
}
impl Iterator for MergeIter {
type Item = Result<Record, ReadError>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(Reverse((_, i))) = self.heap.pop() {
let r = self.peeked[i]
.take()
.expect("heap entry must have a peeked record");
self.refill(i);
return Some(Ok(r));
}
self.pending_err.take().map(Err)
}
}
pub struct ScanIter {
inner: Box<dyn Iterator<Item = Result<Record, ReadError>> + Send>,
}
impl ScanIter {
pub(crate) fn build(
manifests: Vec<Arc<Mutex<SegmentManifest>>>,
key: Option<Arc<KeyRing>>,
from_id: u64,
to_id: u64,
) -> Result<Self, ReadError> {
let mut scanners: Vec<ShardScanner> = Vec::with_capacity(manifests.len());
for m in manifests {
scanners.push(ShardScanner::new(m, key.clone(), from_id, to_id)?);
}
Ok(match scanners.len() {
1 => ScanIter {
inner: Box::new(scanners.pop().expect("exactly one scanner")),
},
_ => ScanIter {
inner: Box::new(MergeIter::new(scanners)?),
},
})
}
}
impl Iterator for ScanIter {
type Item = Result<Record, ReadError>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}