Skip to main content

terminus_store/layer/
id_map.rs

1use super::*;
2use crate::storage::{BitIndexMaps, FileLoad, FileStore, IdMapFiles};
3use std::convert::TryInto;
4use std::io;
5use tdb_succinct::util::sorted_iterator;
6use tdb_succinct::*;
7
8#[derive(Clone)]
9pub struct IdMap {
10    pub id_wtree: Option<WaveletTree>,
11}
12
13impl Default for IdMap {
14    fn default() -> Self {
15        Self::from_parts(None)
16    }
17}
18
19impl IdMap {
20    pub fn from_maps(maps: BitIndexMaps, width: u8) -> Self {
21        let bitindex = BitIndex::from_maps(maps.bits_map, maps.blocks_map, maps.sblocks_map);
22        let id_wtree = WaveletTree::from_parts(bitindex, width);
23
24        Self::from_parts(Some(id_wtree))
25    }
26
27    pub fn from_parts(id_wtree: Option<WaveletTree>) -> Self {
28        IdMap { id_wtree }
29    }
30
31    pub fn outer_to_inner(&self, id: u64) -> u64 {
32        self.id_wtree
33            .as_ref()
34            .and_then(|wtree| {
35                if id > wtree.len() as u64 {
36                    None
37                } else {
38                    Some(wtree.lookup_one(id - 1).unwrap() + 1)
39                }
40            })
41            .unwrap_or(id)
42    }
43
44    pub fn inner_to_outer(&self, id: u64) -> u64 {
45        self.id_wtree
46            .as_ref()
47            .and_then(|wtree| {
48                if id > wtree.len() as u64 {
49                    None
50                } else {
51                    let id: usize = id.try_into().unwrap();
52                    Some(wtree.decode_one(id - 1) + 1)
53                }
54            })
55            .unwrap_or(id)
56    }
57}
58
59pub async fn memory_construct_idmaps<F: 'static + FileLoad + FileStore>(
60    input: &InternalLayer,
61    idmap_files: IdMapFiles<F>,
62) -> io::Result<()> {
63    let layers = input.immediate_layers();
64
65    construct_idmaps_from_layers(&layers, idmap_files).await
66}
67
68pub async fn memory_construct_idmaps_upto<F: 'static + FileLoad + FileStore>(
69    input: &InternalLayer,
70    upto_layer_id: [u32; 5],
71    idmap_files: IdMapFiles<F>,
72) -> io::Result<()> {
73    let layers = input.immediate_layers_upto(upto_layer_id);
74
75    construct_idmaps_from_layers(&layers, idmap_files).await
76}
77
78pub async fn construct_idmaps_from_structures<F: 'static + FileLoad + FileStore>(
79    node_dicts: Vec<StringDict>,
80    predicate_dicts: Vec<StringDict>,
81    value_dicts: Vec<TypedDict>,
82    node_value_idmaps: &[IdMap],
83    predicate_idmaps: &[IdMap],
84    idmap_files: IdMapFiles<F>,
85) -> io::Result<()> {
86    debug_assert!(node_dicts.len() == predicate_dicts.len());
87    debug_assert!(node_dicts.len() == value_dicts.len());
88    debug_assert!(node_dicts.len() == node_value_idmaps.len());
89    debug_assert!(node_dicts.len() == predicate_idmaps.len());
90    let len = node_dicts.len();
91
92    let mut node_iters = Vec::with_capacity(len);
93    let mut node_offset = 0;
94    let node_entries_len: Vec<_> = node_dicts.iter().map(|d| d.num_entries()).collect();
95    for (ix, dict) in node_dicts.into_iter().enumerate() {
96        let idmap = node_value_idmaps[ix].clone();
97        let num_entries = dict.num_entries();
98        node_iters.push(
99            dict.into_iter()
100                .enumerate()
101                .map(move |(i, e)| (idmap.inner_to_outer(i as u64 + 1) + node_offset as u64, e)),
102        );
103
104        node_offset += num_entries + value_dicts[ix].num_entries();
105    }
106
107    let mut value_iters = Vec::with_capacity(len);
108    let mut value_offset = 0;
109    for (ix, dict) in value_dicts.into_iter().enumerate() {
110        let idmap = node_value_idmaps[ix].clone();
111        let node_count = node_entries_len[ix];
112        let num_entries = dict.num_entries();
113        value_iters.push(dict.into_iter().enumerate().map(move |(i, e)| {
114            (
115                idmap.inner_to_outer(i as u64 + node_count as u64 + 1) + value_offset as u64,
116                e,
117            )
118        }));
119
120        value_offset += node_count + num_entries;
121    }
122
123    let mut predicate_iters = Vec::with_capacity(len);
124    let mut predicate_offset = 0;
125    for (ix, dict) in predicate_dicts.into_iter().enumerate() {
126        let idmap = predicate_idmaps[ix].clone();
127        let num_entries = dict.num_entries();
128        predicate_iters.push(dict.into_iter().enumerate().map(move |(i, e)| {
129            (
130                idmap.inner_to_outer(i as u64 + 1) + predicate_offset as u64,
131                e,
132            )
133        }));
134
135        predicate_offset += num_entries;
136    }
137
138    let entry_comparator = |vals: &[Option<&(u64, SizedDictEntry)>]| {
139        vals.iter()
140            .enumerate()
141            .filter(|(_, x)| x.is_some())
142            .min_by(|(_, x), (_, y)| x.unwrap().1.cmp(&y.unwrap().1))
143            .map(|x| x.0)
144    };
145
146    let typed_entry_comparator = |vals: &[Option<&(u64, TypedDictEntry)>]| {
147        vals.iter()
148            .enumerate()
149            .filter(|(_, x)| x.is_some())
150            .min_by(|(_, x), (_, y)| x.unwrap().1.cmp(&y.unwrap().1))
151            .map(|x| x.0)
152    };
153
154    let sorted_node_iter = sorted_iterator(node_iters, entry_comparator)
155        .map(|(i, s)| (i, TypedDictEntry::new(Datatype::String, s)));
156    let sorted_value_iter = sorted_iterator(value_iters, typed_entry_comparator);
157    let sorted_node_value_iter = sorted_node_iter
158        .chain(sorted_value_iter)
159        .map(|(id, _)| id - 1);
160    let sorted_predicate_iter =
161        sorted_iterator(predicate_iters, entry_comparator).map(|(id, _)| id - 1);
162
163    let node_value_width = util::calculate_width(node_offset as u64);
164    let node_value_build_task = tokio::spawn(build_wavelet_tree_from_iter(
165        node_value_width,
166        sorted_node_value_iter,
167        idmap_files.node_value_idmap_files.bits_file,
168        idmap_files.node_value_idmap_files.blocks_file,
169        idmap_files.node_value_idmap_files.sblocks_file,
170    ));
171    let predicate_width = util::calculate_width(predicate_offset as u64);
172    let predicate_build_task = tokio::spawn(build_wavelet_tree_from_iter(
173        predicate_width,
174        sorted_predicate_iter,
175        idmap_files.predicate_idmap_files.bits_file,
176        idmap_files.predicate_idmap_files.blocks_file,
177        idmap_files.predicate_idmap_files.sblocks_file,
178    ));
179
180    node_value_build_task.await??;
181    predicate_build_task.await?
182}
183
184async fn construct_idmaps_from_layers<F: 'static + FileLoad + FileStore>(
185    layers: &[&InternalLayer],
186    idmap_files: IdMapFiles<F>,
187) -> io::Result<()> {
188    let node_dicts: Vec<_> = layers
189        .iter()
190        .map(|layer| layer.node_dictionary().clone())
191        .collect();
192
193    let predicate_dicts: Vec<_> = layers
194        .iter()
195        .map(|layer| layer.predicate_dictionary().clone())
196        .collect();
197
198    let value_dicts: Vec<_> = layers
199        .iter()
200        .map(|layer| layer.value_dictionary().clone())
201        .collect();
202
203    let node_value_idmaps: Vec<_> = layers
204        .iter()
205        .map(|layer| layer.node_value_id_map().clone())
206        .collect();
207
208    let predicate_idmaps: Vec<_> = layers
209        .iter()
210        .map(|layer| layer.predicate_id_map().clone())
211        .collect();
212
213    construct_idmaps_from_structures(
214        node_dicts,
215        predicate_dicts,
216        value_dicts,
217        &node_value_idmaps,
218        &predicate_idmaps,
219        idmap_files,
220    )
221    .await
222}