json_surf/
seed.rs

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
11/// Resolve home
12pub(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
22/// Resolve Index
23pub(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
30/// Create a MMap dir
31pub(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
40/// Open a store or create & open using a schema
41pub(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
59/// Convenience method to open writer
60pub(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
74/// Convenience method to open reader
75pub(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}