use std::path::PathBuf;
pub mod apply;
pub mod approximate_counter;
pub mod counter_builder;
pub mod definition_update;
pub mod lucene_directory;
pub mod lucene_import;
pub mod lucene_reindex;
pub mod plan;
pub mod prepared;
pub mod property_builder;
pub mod property_collector;
pub mod selection;
pub use apply::{DefinitionReport, ReindexOutcome};
pub use lucene_directory::{DEFAULT_BLOB_SIZE, DirectoryListing, OakDirectoryWriter};
pub use plan::{NoWorkReason, ReindexAction, ReindexPlan, ReindexWarning};
pub use prepared::{
PreparedReindex, plan_reindex, plan_reindex_with_progress, reindex, reindex_with_progress,
};
pub use crate::external_sort::{
MAXIMUM_FAN_IN, RunLocation, SortBudget, SortedPass, SortedPasses, SpillRecord,
};
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct IndexEntry {
pub key: String,
pub path: String,
}
impl IndexEntry {
#[must_use]
pub fn new(key: impl Into<String>, path: impl Into<String>) -> Self {
Self {
key: key.into(),
path: path.into(),
}
}
fn path_elements(&self) -> impl Iterator<Item = &str> {
self.path.split('/').filter(|element| !element.is_empty())
}
}
impl Ord for IndexEntry {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.key.as_bytes().cmp(other.key.as_bytes()).then_with(|| {
self.path_elements()
.map(str::as_bytes)
.cmp(other.path_elements().map(str::as_bytes))
})
}
}
impl PartialOrd for IndexEntry {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl SpillRecord for IndexEntry {
fn encode(&self, buffer: &mut Vec<u8>) {
let key = self.key.as_bytes();
buffer.extend_from_slice(&u32::try_from(key.len()).unwrap_or(u32::MAX).to_le_bytes());
buffer.extend_from_slice(key);
buffer.extend_from_slice(self.path.as_bytes());
}
fn decode(bytes: &[u8]) -> crate::Result<Self> {
let invalid = || crate::Error::InvalidFormat {
details: "a spilled index entry is truncated".to_owned(),
};
let length: [u8; 4] = bytes
.get(..4)
.ok_or_else(invalid)?
.try_into()
.map_err(|_| invalid())?;
let length = u32::from_le_bytes(length) as usize;
let key = bytes.get(4..4 + length).ok_or_else(invalid)?;
let path = bytes.get(4 + length..).ok_or_else(invalid)?;
Ok(Self {
key: String::from_utf8_lossy(key).into_owned(),
path: String::from_utf8_lossy(path).into_owned(),
})
}
fn resident_size(&self) -> usize {
self.key.len() + self.path.len()
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum WorkDirectory {
OperatorNamed(PathBuf),
Default,
}
impl WorkDirectory {
#[must_use]
pub fn path(&self) -> PathBuf {
match self {
Self::OperatorNamed(path) => path.clone(),
Self::Default => std::env::temp_dir(),
}
}
#[must_use]
pub fn is_operator_named(&self) -> bool {
matches!(self, Self::OperatorNamed(_))
}
}
pub const DEFAULT_SORT_BUDGET_BYTES: usize = 64 * 1024 * 1024;
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ReindexOptions {
requested_paths: Vec<String>,
from_head: bool,
work_directory: WorkDirectory,
sort_budget_bytes: usize,
binary_text_policy: Option<crate::index::lucene::documents::binaries::BinaryTextPolicy>,
}
impl Default for ReindexOptions {
fn default() -> Self {
Self::new()
}
}
impl ReindexOptions {
#[must_use]
pub fn new() -> Self {
Self {
requested_paths: Vec::new(),
from_head: false,
work_directory: WorkDirectory::Default,
sort_budget_bytes: DEFAULT_SORT_BUDGET_BYTES,
binary_text_policy: None,
}
}
#[must_use]
pub fn with_indexes(mut self, paths: impl IntoIterator<Item = String>) -> Self {
self.requested_paths = paths.into_iter().collect();
self
}
#[must_use]
pub fn with_from_head(mut self, from_head: bool) -> Self {
self.from_head = from_head;
self
}
#[must_use]
pub fn with_work_directory(mut self, directory: WorkDirectory) -> Self {
self.work_directory = directory;
self
}
#[must_use]
pub fn with_binary_text_policy(
mut self,
policy: crate::index::lucene::documents::binaries::BinaryTextPolicy,
) -> Self {
self.binary_text_policy = Some(policy);
self
}
#[must_use]
pub fn with_sort_budget_bytes(mut self, bytes: usize) -> Self {
self.sort_budget_bytes = bytes;
self
}
#[must_use]
pub fn requested_paths(&self) -> &[String] {
&self.requested_paths
}
#[must_use]
pub fn from_head(&self) -> bool {
self.from_head
}
#[must_use]
pub fn work_directory(&self) -> &WorkDirectory {
&self.work_directory
}
#[must_use]
pub fn sort_budget_bytes(&self) -> usize {
self.sort_budget_bytes
}
#[must_use]
pub fn binary_text_policy(
&self,
) -> Option<&crate::index::lucene::documents::binaries::BinaryTextPolicy> {
self.binary_text_policy.as_ref()
}
}