1use std::collections::HashMap;
4use std::io;
5
6use async_trait::async_trait;
7
8use super::file::*;
9use super::label::*;
10use super::layer::*;
11
12pub use tdb_succinct::storage::memory::*;
13
14#[derive(Clone, Default)]
15pub struct MemoryLayerStore {
16 layers: futures_locks::RwLock<HashMap<[u32; 5], HashMap<String, MemoryBackedStore>>>,
17}
18
19impl MemoryLayerStore {
20 pub fn new() -> Self {
21 Self::default()
22 }
23}
24
25#[async_trait]
26impl PersistentLayerStore for MemoryLayerStore {
27 type File = MemoryBackedStore;
28
29 async fn directories(&self) -> io::Result<Vec<[u32; 5]>> {
30 let guard = self.layers.read().await;
31 Ok(guard.keys().cloned().collect())
32 }
33
34 async fn create_named_directory(&self, name: [u32; 5]) -> io::Result<[u32; 5]> {
35 let mut guard = self.layers.write().await;
36 guard.insert(name, HashMap::new());
37
38 Ok(name)
39 }
40
41 async fn directory_exists(&self, name: [u32; 5]) -> io::Result<bool> {
42 let guard = self.layers.read().await;
43 Ok(guard.contains_key(&name))
44 }
45
46 async fn file_exists(&self, directory: [u32; 5], file: &str) -> io::Result<bool> {
47 let guard = self.layers.read().await;
48 if let Some(files) = guard.get(&directory) {
49 if let Some(file) = files.get(file) {
50 file.exists().await
51 } else {
52 Ok(false)
53 }
54 } else {
55 Ok(false)
56 }
57 }
58
59 async fn get_file(&self, directory: [u32; 5], name: &str) -> io::Result<Self::File> {
60 let guard = self.layers.read().await;
61 if let Some(files) = guard.get(&directory) {
62 if let Some(file) = files.get(name) {
63 Ok(file.clone())
64 } else {
65 std::mem::drop(guard); let mut guard = self.layers.write().await;
67 let files = guard.get_mut(&directory).unwrap();
68 let file = MemoryBackedStore::new();
69 let result = file.clone();
70 files.insert(name.to_string(), file);
71 Ok(result)
72 }
73 } else {
74 Err(io::Error::new(io::ErrorKind::NotFound, "layer not found"))
75 }
76 }
77}
78
79#[derive(Clone, Default)]
80pub struct MemoryLabelStore {
81 labels: futures_locks::RwLock<HashMap<String, Label>>,
82}
83
84impl MemoryLabelStore {
85 pub fn new() -> MemoryLabelStore {
86 Default::default()
87 }
88}
89
90#[async_trait]
91impl LabelStore for MemoryLabelStore {
92 async fn labels(&self) -> io::Result<Vec<Label>> {
93 let labels = self.labels.read().await;
94 Ok(labels.values().cloned().collect())
95 }
96
97 async fn create_label(&self, name: &str) -> io::Result<Label> {
98 let label = Label::new_empty(name);
99
100 let mut labels = self.labels.write().await;
101 if labels.get(&label.name).is_some() {
102 Err(std::io::Error::new(
103 std::io::ErrorKind::InvalidInput,
104 "label already exists",
105 ))
106 } else {
107 labels.insert(label.name.clone(), label.clone());
108 Ok(label)
109 }
110 }
111
112 async fn get_label(&self, name: &str) -> io::Result<Option<Label>> {
113 let name = name.to_owned();
114 let labels = self.labels.read().await;
115 Ok(labels.get(&name).cloned())
116 }
117
118 async fn set_label_option(
119 &self,
120 label: &Label,
121 layer: Option<[u32; 5]>,
122 ) -> io::Result<Option<Label>> {
123 let new_label = label.with_updated_layer(layer);
124
125 let mut labels = self.labels.write().await;
126
127 match labels.get(&new_label.name) {
128 None => Err(std::io::Error::new(
129 std::io::ErrorKind::InvalidInput,
130 "label does not exist",
131 )),
132 Some(old_label) => {
133 if old_label.version + 1 != new_label.version {
134 Ok(None)
135 } else {
136 labels.insert(new_label.name.clone(), new_label.clone());
137
138 Ok(Some(new_label))
139 }
140 }
141 }
142 }
143
144 async fn delete_label(&self, name: &str) -> io::Result<bool> {
145 let mut labels = self.labels.write().await;
146
147 Ok(labels.remove(name).is_some())
148 }
149}
150
151#[cfg(test)]
152pub fn base_layer_memory_files() -> BaseLayerFiles<MemoryBackedStore> {
153 BaseLayerFiles {
154 node_dictionary_files: DictionaryFiles {
155 blocks_file: MemoryBackedStore::new(),
156 offsets_file: MemoryBackedStore::new(),
157 },
158 predicate_dictionary_files: DictionaryFiles {
159 blocks_file: MemoryBackedStore::new(),
160 offsets_file: MemoryBackedStore::new(),
161 },
162 value_dictionary_files: TypedDictionaryFiles {
163 types_present_file: MemoryBackedStore::new(),
164 type_offsets_file: MemoryBackedStore::new(),
165 blocks_file: MemoryBackedStore::new(),
166 offsets_file: MemoryBackedStore::new(),
167 },
168
169 id_map_files: IdMapFiles {
170 node_value_idmap_files: BitIndexFiles {
171 bits_file: MemoryBackedStore::new(),
172 blocks_file: MemoryBackedStore::new(),
173 sblocks_file: MemoryBackedStore::new(),
174 },
175 predicate_idmap_files: BitIndexFiles {
176 bits_file: MemoryBackedStore::new(),
177 blocks_file: MemoryBackedStore::new(),
178 sblocks_file: MemoryBackedStore::new(),
179 },
180 },
181
182 subjects_file: MemoryBackedStore::new(),
183 objects_file: MemoryBackedStore::new(),
184
185 s_p_adjacency_list_files: AdjacencyListFiles {
186 bitindex_files: BitIndexFiles {
187 bits_file: MemoryBackedStore::new(),
188 blocks_file: MemoryBackedStore::new(),
189 sblocks_file: MemoryBackedStore::new(),
190 },
191 nums_file: MemoryBackedStore::new(),
192 },
193 sp_o_adjacency_list_files: AdjacencyListFiles {
194 bitindex_files: BitIndexFiles {
195 bits_file: MemoryBackedStore::new(),
196 blocks_file: MemoryBackedStore::new(),
197 sblocks_file: MemoryBackedStore::new(),
198 },
199 nums_file: MemoryBackedStore::new(),
200 },
201 o_ps_adjacency_list_files: AdjacencyListFiles {
202 bitindex_files: BitIndexFiles {
203 bits_file: MemoryBackedStore::new(),
204 blocks_file: MemoryBackedStore::new(),
205 sblocks_file: MemoryBackedStore::new(),
206 },
207 nums_file: MemoryBackedStore::new(),
208 },
209 predicate_wavelet_tree_files: BitIndexFiles {
210 bits_file: MemoryBackedStore::new(),
211 blocks_file: MemoryBackedStore::new(),
212 sblocks_file: MemoryBackedStore::new(),
213 },
214 }
215}
216
217#[cfg(test)]
218pub fn child_layer_memory_files() -> ChildLayerFiles<MemoryBackedStore> {
219 ChildLayerFiles {
220 node_dictionary_files: DictionaryFiles {
221 blocks_file: MemoryBackedStore::new(),
222 offsets_file: MemoryBackedStore::new(),
223 },
224 predicate_dictionary_files: DictionaryFiles {
225 blocks_file: MemoryBackedStore::new(),
226 offsets_file: MemoryBackedStore::new(),
227 },
228 value_dictionary_files: TypedDictionaryFiles {
229 types_present_file: MemoryBackedStore::new(),
230 type_offsets_file: MemoryBackedStore::new(),
231 blocks_file: MemoryBackedStore::new(),
232 offsets_file: MemoryBackedStore::new(),
233 },
234
235 id_map_files: IdMapFiles {
236 node_value_idmap_files: BitIndexFiles {
237 bits_file: MemoryBackedStore::new(),
238 blocks_file: MemoryBackedStore::new(),
239 sblocks_file: MemoryBackedStore::new(),
240 },
241 predicate_idmap_files: BitIndexFiles {
242 bits_file: MemoryBackedStore::new(),
243 blocks_file: MemoryBackedStore::new(),
244 sblocks_file: MemoryBackedStore::new(),
245 },
246 },
247
248 pos_subjects_file: MemoryBackedStore::new(),
249 pos_objects_file: MemoryBackedStore::new(),
250 neg_subjects_file: MemoryBackedStore::new(),
251 neg_objects_file: MemoryBackedStore::new(),
252
253 pos_s_p_adjacency_list_files: AdjacencyListFiles {
254 bitindex_files: BitIndexFiles {
255 bits_file: MemoryBackedStore::new(),
256 blocks_file: MemoryBackedStore::new(),
257 sblocks_file: MemoryBackedStore::new(),
258 },
259 nums_file: MemoryBackedStore::new(),
260 },
261 pos_sp_o_adjacency_list_files: AdjacencyListFiles {
262 bitindex_files: BitIndexFiles {
263 bits_file: MemoryBackedStore::new(),
264 blocks_file: MemoryBackedStore::new(),
265 sblocks_file: MemoryBackedStore::new(),
266 },
267 nums_file: MemoryBackedStore::new(),
268 },
269 pos_o_ps_adjacency_list_files: AdjacencyListFiles {
270 bitindex_files: BitIndexFiles {
271 bits_file: MemoryBackedStore::new(),
272 blocks_file: MemoryBackedStore::new(),
273 sblocks_file: MemoryBackedStore::new(),
274 },
275 nums_file: MemoryBackedStore::new(),
276 },
277 neg_s_p_adjacency_list_files: AdjacencyListFiles {
278 bitindex_files: BitIndexFiles {
279 bits_file: MemoryBackedStore::new(),
280 blocks_file: MemoryBackedStore::new(),
281 sblocks_file: MemoryBackedStore::new(),
282 },
283 nums_file: MemoryBackedStore::new(),
284 },
285 neg_sp_o_adjacency_list_files: AdjacencyListFiles {
286 bitindex_files: BitIndexFiles {
287 bits_file: MemoryBackedStore::new(),
288 blocks_file: MemoryBackedStore::new(),
289 sblocks_file: MemoryBackedStore::new(),
290 },
291 nums_file: MemoryBackedStore::new(),
292 },
293 neg_o_ps_adjacency_list_files: AdjacencyListFiles {
294 bitindex_files: BitIndexFiles {
295 bits_file: MemoryBackedStore::new(),
296 blocks_file: MemoryBackedStore::new(),
297 sblocks_file: MemoryBackedStore::new(),
298 },
299 nums_file: MemoryBackedStore::new(),
300 },
301 pos_predicate_wavelet_tree_files: BitIndexFiles {
302 bits_file: MemoryBackedStore::new(),
303 blocks_file: MemoryBackedStore::new(),
304 sblocks_file: MemoryBackedStore::new(),
305 },
306 neg_predicate_wavelet_tree_files: BitIndexFiles {
307 bits_file: MemoryBackedStore::new(),
308 blocks_file: MemoryBackedStore::new(),
309 sblocks_file: MemoryBackedStore::new(),
310 },
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317 use crate::layer::*;
318 use tokio::io::{AsyncReadExt, AsyncWriteExt};
319
320 #[tokio::test]
321 async fn write_and_read_memory_backed() {
322 let file = MemoryBackedStore::new();
323
324 let mut w = file.open_write().await.unwrap();
325 w.write_all(&[1, 2, 3]).await.unwrap();
326 w.sync_all().await.unwrap();
327 let mut buf = Vec::new();
328 file.open_read()
329 .await
330 .unwrap()
331 .read_to_end(&mut buf)
332 .await
333 .unwrap();
334
335 assert_eq!(vec![1, 2, 3], buf);
336 }
337
338 #[tokio::test]
339 async fn write_and_map_memory_backed() {
340 let file = MemoryBackedStore::new();
341
342 let mut w = file.open_write().await.unwrap();
343 w.write_all(&[1, 2, 3]).await.unwrap();
344 w.sync_all().await.unwrap();
345 let map = file.map().await.unwrap();
346
347 assert_eq!(vec![1, 2, 3], map.as_ref());
348 }
349
350 #[tokio::test]
351 async fn create_layers_from_memory_store() {
352 let store = MemoryLayerStore::new();
353 let mut builder = store.create_base_layer().await.unwrap();
354 let base_name = builder.name();
355
356 builder.add_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
357 builder.add_value_triple(ValueTriple::new_string_value("pig", "says", "oink"));
358 builder.add_value_triple(ValueTriple::new_string_value("duck", "says", "quack"));
359
360 builder.commit_boxed().await.unwrap();
361 builder = store.create_child_layer(base_name).await.unwrap();
362 let child_name = builder.name();
363
364 builder.remove_value_triple(ValueTriple::new_string_value("duck", "says", "quack"));
365 builder.add_value_triple(ValueTriple::new_node("cow", "likes", "pig"));
366
367 builder.commit_boxed().await.unwrap();
368 let layer = store.get_layer(child_name).await.unwrap().unwrap();
369
370 assert!(layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo")));
371 assert!(layer.value_triple_exists(&ValueTriple::new_string_value("pig", "says", "oink")));
372 assert!(layer.value_triple_exists(&ValueTriple::new_node("cow", "likes", "pig")));
373 assert!(!layer.value_triple_exists(&ValueTriple::new_string_value("duck", "says", "quack")));
374 }
375
376 #[tokio::test]
377 async fn memory_create_and_retrieve_equal_label() {
378 let store = MemoryLabelStore::new();
379 let foo = store.create_label("foo").await.unwrap();
380 assert_eq!(foo, store.get_label("foo").await.unwrap().unwrap());
381 }
382
383 #[tokio::test]
384 async fn memory_update_label_succeeds() {
385 let store = MemoryLabelStore::new();
386 let foo = store.create_label("foo").await.unwrap();
387
388 assert_eq!(
389 1,
390 store
391 .set_label(&foo, [6, 7, 8, 9, 10])
392 .await
393 .unwrap()
394 .unwrap()
395 .version
396 );
397
398 assert_eq!(1, store.get_label("foo").await.unwrap().unwrap().version);
399 }
400
401 #[tokio::test]
402 async fn memory_update_label_twice_from_same_label_object_fails() {
403 let store = MemoryLabelStore::new();
404 let foo = store.create_label("foo").await.unwrap();
405
406 assert!(store
407 .set_label(&foo, [6, 7, 8, 9, 10])
408 .await
409 .unwrap()
410 .is_some());
411 assert!(store
412 .set_label(&foo, [1, 1, 1, 1, 1])
413 .await
414 .unwrap()
415 .is_none());
416 }
417
418 #[tokio::test]
419 async fn memory_update_label_twice_from_updated_label_object_succeeds() {
420 let store = MemoryLabelStore::new();
421 let foo = store.create_label("foo").await.unwrap();
422
423 let foo2 = store
424 .set_label(&foo, [6, 7, 8, 9, 10])
425 .await
426 .unwrap()
427 .unwrap();
428 assert!(store
429 .set_label(&foo2, [1, 1, 1, 1, 1])
430 .await
431 .unwrap()
432 .is_some());
433 }
434
435 #[tokio::test]
436 async fn create_and_delete_label() {
437 let store = MemoryLabelStore::new();
438
439 store.create_label("foo").await.unwrap();
440 assert!(store.get_label("foo").await.unwrap().is_some());
441 assert!(store.delete_label("foo").await.unwrap());
442 assert!(store.get_label("foo").await.unwrap().is_none());
443 }
444
445 #[tokio::test]
446 async fn delete_nonexistent_label() {
447 let store = MemoryLabelStore::new();
448
449 assert!(!store.delete_label("foo").await.unwrap());
450 }
451}