use std::path::{Path, PathBuf};
use std::fs::create_dir_all;
use tantivy::directory::MmapDirectory;
use tantivy::{Index, ReloadPolicy, IndexWriter, IndexReader};
use crate::prelude::*;
use tantivy::schema::Schema;
pub(crate) fn resolve_home<T: AsRef<str>>(home: Option<T>) -> Result<PathBuf, IndexError> {
let home = match &home {
Some(h) => h.as_ref(),
None => "indexes"
};
let home = Path::new(home);
let _ = create_dir_all(home)?;
Ok(home.to_owned())
}
pub(crate) fn resolve_index_directory_path<T: AsRef<str>>(name: T, home: Option<T>) -> Result<PathBuf, IndexError> {
let home = resolve_home(home)?;
let path = home.join(name.as_ref());
Ok(path)
}
pub(crate) fn open_mmap_directory(path: PathBuf) -> Result<MmapDirectory, IndexError> {
if !path.exists() {
let _ = create_dir_all(&path)?;
}
let dir = MmapDirectory::open(path)?;
Ok(dir)
}
pub(crate) fn open_index(dir: MmapDirectory, schema: Option<&Schema>) -> Result<Index, IndexError> {
let index = if Index::exists(&dir) {
Index::open(dir)
} else {
if let None = schema {
let error = IndexError::new(
"Unable to create index",
"Schema is required for new index",
);
return Err(error);
}
let schema = schema.unwrap();
Index::create(dir, schema.clone())
}?;
Ok(index)
}
pub(crate) fn open_index_writer(index: &Index) -> Result<IndexWriter, IndexError> {
let index_writer = index.writer(50_000_000)
.map_err(|e| {
let reason = e.to_string();
let error = IndexError::new(
"Unable to create index writer",
reason.as_str(),
);
error
})?;
Ok(index_writer)
}
pub(crate) fn open_index_reader(index: &Index) -> Result<IndexReader, IndexError> {
let index_reader = index
.reader_builder()
.reload_policy(ReloadPolicy::OnCommit)
.try_into().map_err(|e| {
let reason = e.to_string();
let error = IndexError::new(
"Unable to create index reader",
reason.as_str(),
);
error
})?;
Ok(index_reader)
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
use std::fs::remove_dir_all;
use super::super::utils;
use serde::Serialize;
use crate::utils::as_value;
#[derive(Serialize)]
struct Dummy {
x: String,
y: String,
z: u64,
}
impl Default for Dummy {
fn default() -> Self {
let x: String = "".to_string();
let y: String = "".to_string();
let z: u64 = 1u64;
Self {
x,
y,
z,
}
}
}
#[test]
fn validate_open_mmap_on_missing_dir() {
let path = random_string(Some(10));
let p = Path::new(&path);
assert!(!p.exists());
let path = PathBuf::from_str(&path);
assert!(path.is_ok());
let path = path.ok().unwrap();
let path = open_mmap_directory(path);
assert!(path.is_ok());
assert!(p.exists());
let _ = remove_dir_all(&p);
}
#[test]
fn validate_open_index_on_missing_dir() {
let data = Dummy {
x: "A".to_owned(),
y: "B".to_owned(),
z: 100,
};
let data = utils::as_value(&data).unwrap();
let (schema, _) = utils::to_schema(&data, None).unwrap();
let path = random_string(Some(10));
let p = Path::new(&path);
assert!(!p.exists());
let path = PathBuf::from_str(&path).unwrap();
let path = open_mmap_directory(path).unwrap();
let result = open_index(path, Some(&schema));
assert!(result.is_ok());
assert!(p.exists());
let _ = remove_dir_all(&p);
}
#[test]
fn error_while_opening_new_index_without_schema() {
let tmp_error_while_opening_new_index_without_schema = "error_while_opening_new_index_without_schema";
let path = Path::new(tmp_error_while_opening_new_index_without_schema);
assert!(!path.exists());
let _ = std::fs::create_dir_all(path);
assert!(path.exists());
let dir = MmapDirectory::open(path).unwrap();
let index = open_index(dir, None);
assert!(index.is_err());
let _ = std::fs::remove_dir_all(path);
}
#[test]
fn error_while_opening_open_index_writer() {
let tmp_error_while_opening_new_index_without_schema = "error_while_opening_open_index_writer";
let path = Path::new(tmp_error_while_opening_new_index_without_schema);
assert!(!path.exists());
let _ = std::fs::create_dir_all(path);
assert!(path.exists());
let dir = MmapDirectory::open(path).unwrap();
let dummy = Dummy::default();
let data = as_value(&dummy).unwrap();
let (schema, _) = to_schema(&data, None).unwrap();
let index = open_index(dir, Some(&schema)).unwrap();
let _ = std::fs::remove_dir_all(path);
let writer = open_index_writer(&index);
assert!(writer.is_err());
}
#[test]
fn error_while_opening_open_index_reader() {
let tmp_error_while_opening_new_index_without_schema = "error_while_opening_open_index_reader";
let path = Path::new(tmp_error_while_opening_new_index_without_schema);
assert!(!path.exists());
let _ = std::fs::create_dir_all(path);
assert!(path.exists());
let dir = MmapDirectory::open(path).unwrap();
let dummy = Dummy::default();
let data = as_value(&dummy).unwrap();
let (schema, _) = to_schema(&data, None).unwrap();
let index = open_index(dir, Some(&schema)).unwrap();
let _ = std::fs::remove_dir_all(path);
let reader = open_index_reader(&index);
assert!(reader.is_err());
}
}