1use std::path::{Path, PathBuf};
2use std::fs::create_dir_all;
3
4use tantivy::directory::MmapDirectory;
5use tantivy::{Index, ReloadPolicy, IndexWriter, IndexReader};
6
7use crate::prelude::*;
8use tantivy::schema::Schema;
9
10
11pub(crate) fn resolve_home<T: AsRef<str>>(home: Option<T>) -> Result<PathBuf, IndexError> {
13 let home = match &home {
14 Some(h) => h.as_ref(),
15 None => "indexes"
16 };
17 let home = Path::new(home);
18 let _ = create_dir_all(home)?;
19 Ok(home.to_owned())
20}
21
22pub(crate) fn resolve_index_directory_path<T: AsRef<str>>(name: T, home: Option<T>) -> Result<PathBuf, IndexError> {
24 let home = resolve_home(home)?;
25 let path = home.join(name.as_ref());
26 Ok(path)
27}
28
29
30pub(crate) fn open_mmap_directory(path: PathBuf) -> Result<MmapDirectory, IndexError> {
32 if !path.exists() {
33 let _ = create_dir_all(&path)?;
34 }
35 let dir = MmapDirectory::open(path)?;
36 Ok(dir)
37}
38
39
40pub(crate) fn open_index(dir: MmapDirectory, schema: Option<&Schema>) -> Result<Index, IndexError> {
42 let index = if Index::exists(&dir) {
43 Index::open(dir)
44 } else {
45 if let None = schema {
46 let error = IndexError::new(
47 "Unable to create index",
48 "Schema is required for new index",
49 );
50 return Err(error);
51 }
52 let schema = schema.unwrap();
53 Index::create(dir, schema.clone())
54 }?;
55
56 Ok(index)
57}
58
59pub(crate) fn open_index_writer(index: &Index) -> Result<IndexWriter, IndexError> {
61 let index_writer = index.writer(50_000_000)
62 .map_err(|e| {
63 let reason = e.to_string();
64 let error = IndexError::new(
65 "Unable to create index writer",
66 reason.as_str(),
67 );
68 error
69 })?;
70 Ok(index_writer)
71}
72
73
74pub(crate) fn open_index_reader(index: &Index) -> Result<IndexReader, IndexError> {
76 let index_reader = index
77 .reader_builder()
78 .reload_policy(ReloadPolicy::OnCommit)
79 .try_into().map_err(|e| {
80 let reason = e.to_string();
81 let error = IndexError::new(
82 "Unable to create index reader",
83 reason.as_str(),
84 );
85 error
86 })?;
87 Ok(index_reader)
88}
89
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use std::str::FromStr;
95 use std::fs::remove_dir_all;
96 use super::super::utils;
97 use serde::Serialize;
98 use crate::utils::as_value;
99
100 #[derive(Serialize)]
101 struct Dummy {
102 x: String,
103 y: String,
104 z: u64,
105 }
106
107 impl Default for Dummy {
108 fn default() -> Self {
109 let x: String = "".to_string();
110 let y: String = "".to_string();
111 let z: u64 = 1u64;
112 Self {
113 x,
114 y,
115 z,
116 }
117 }
118 }
119
120
121 #[test]
122 fn validate_open_mmap_on_missing_dir() {
123 let path = random_string(Some(10));
124 let p = Path::new(&path);
125 assert!(!p.exists());
126 let path = PathBuf::from_str(&path);
127 assert!(path.is_ok());
128 let path = path.ok().unwrap();
129 let path = open_mmap_directory(path);
130 assert!(path.is_ok());
131 assert!(p.exists());
132 let _ = remove_dir_all(&p);
133 }
134
135 #[test]
136 fn validate_open_index_on_missing_dir() {
137 let data = Dummy {
138 x: "A".to_owned(),
139 y: "B".to_owned(),
140 z: 100,
141 };
142 let data = utils::as_value(&data).unwrap();
143 let (schema, _) = utils::to_schema(&data, None).unwrap();
144 let path = random_string(Some(10));
145 let p = Path::new(&path);
146 assert!(!p.exists());
147 let path = PathBuf::from_str(&path).unwrap();
148 let path = open_mmap_directory(path).unwrap();
149 let result = open_index(path, Some(&schema));
150 assert!(result.is_ok());
151 assert!(p.exists());
152 let _ = remove_dir_all(&p);
153 }
154
155 #[test]
156 fn error_while_opening_new_index_without_schema() {
157 let tmp_error_while_opening_new_index_without_schema = "error_while_opening_new_index_without_schema";
158
159 let path = Path::new(tmp_error_while_opening_new_index_without_schema);
160 assert!(!path.exists());
161 let _ = std::fs::create_dir_all(path);
162 assert!(path.exists());
163
164
165 let dir = MmapDirectory::open(path).unwrap();
166 let index = open_index(dir, None);
167 assert!(index.is_err());
168 let _ = std::fs::remove_dir_all(path);
169 }
170
171 #[test]
172 fn error_while_opening_open_index_writer() {
173 let tmp_error_while_opening_new_index_without_schema = "error_while_opening_open_index_writer";
174
175 let path = Path::new(tmp_error_while_opening_new_index_without_schema);
176 assert!(!path.exists());
177 let _ = std::fs::create_dir_all(path);
178 assert!(path.exists());
179
180
181 let dir = MmapDirectory::open(path).unwrap();
182
183
184 let dummy = Dummy::default();
185 let data = as_value(&dummy).unwrap();
186 let (schema, _) = to_schema(&data, None).unwrap();
187 let index = open_index(dir, Some(&schema)).unwrap();
188
189 let _ = std::fs::remove_dir_all(path);
190
191 let writer = open_index_writer(&index);
192 assert!(writer.is_err());
193 }
194
195 #[test]
196 fn error_while_opening_open_index_reader() {
197 let tmp_error_while_opening_new_index_without_schema = "error_while_opening_open_index_reader";
198
199 let path = Path::new(tmp_error_while_opening_new_index_without_schema);
200 assert!(!path.exists());
201 let _ = std::fs::create_dir_all(path);
202 assert!(path.exists());
203
204
205 let dir = MmapDirectory::open(path).unwrap();
206
207
208 let dummy = Dummy::default();
209 let data = as_value(&dummy).unwrap();
210 let (schema, _) = to_schema(&data, None).unwrap();
211 let index = open_index(dir, Some(&schema)).unwrap();
212
213 let _ = std::fs::remove_dir_all(path);
214
215 let reader = open_index_reader(&index);
216 assert!(reader.is_err());
217 }
218}