diff --git a/src/structure/adjacencylist.rs b/src/structure/adjacencylist.rs index 5a123a78..6b2abd83 100644 --- a/src/structure/adjacencylist.rs +++ b/src/structure/adjacencylist.rs @@ -108,7 +108,7 @@ impl AdjacencyList { self.nums.entry(pos.try_into().unwrap()) } - pub fn get(&self, index: u64) -> LogArray { + pub fn get(&self, index: u64) -> MonotonicLogArray { if index < 1 { panic!("minimum index has to be 1"); } @@ -124,7 +124,7 @@ impl AdjacencyList { let end = self.bits.select1(index).unwrap(); let length = end - start + 1; - self.nums.slice(start as usize, length as usize) + MonotonicLogArray::from_logarray(self.nums.slice(start as usize, length as usize)) } pub fn iter(&self) -> AdjacencyListIterator { @@ -439,6 +439,7 @@ impl AdjacencyListBufBuilder { } } +#[derive(Clone)] pub struct AdjacencyListBuffers { nums: Bytes, bits: Bytes, diff --git a/src/structure/indexed_property.rs b/src/structure/indexed_property.rs index 4608f246..e9e34c25 100644 --- a/src/structure/indexed_property.rs +++ b/src/structure/indexed_property.rs @@ -1,58 +1,126 @@ -use bytes::{BufMut, Bytes}; +use bytes::{Bytes, BytesMut}; -use super::{util::calculate_width, LogArrayBufBuilder, AdjacencyListBuilder, UnindexedAdjacencyListBuilder, BitArrayFileBuilder}; +use super::{ + util::calculate_width, AdjacencyList, AdjacencyListBufBuilder, AdjacencyListBuffers, LogArray, + LogArrayBufBuilder, MonotonicLogArray, +}; -struct IndexPropertyBuilderBuffers<'a, B: BufMut> { - subjects_logarray_buf: &'a mut B, - index_logarray_buf: &'a mut B, - boundaries_bitarray_buf: &'a mut B, - boundaries_bitindex_blocks_buf: &'a mut B, - boundaries_bitindex_sblocks_buf: &'a mut B, +#[derive(Clone)] +pub struct IndexPropertyBuffers { + subjects_logarray_buf: Bytes, + adjacency_bufs: AdjacencyListBuffers, + objects_logarray_buf: Bytes, } -struct IndexedPropertyBuilder { +pub struct IndexedPropertyBuilder { added: Vec<(u64, usize, u64)>, } impl IndexedPropertyBuilder { - fn new() -> Self { + pub fn new() -> Self { Self { added: Vec::new() } } - fn add(&mut self, subject_id: u64, array_index: usize, object_id: u64) { + pub fn add(&mut self, subject_id: u64, array_index: usize, object_id: u64) { self.added.push((subject_id, array_index, object_id)); } - fn remove(&mut self, subject_id: u64, array_index: usize) { + pub fn remove(&mut self, subject_id: u64, array_index: usize) { self.added.push((subject_id, array_index, 0)); } - fn finalize(mut self, buffers: &mut IndexPropertyBuilderBuffers) { + pub fn finalize(mut self) -> IndexPropertyBuffers { if self.added.len() == 0 { panic!("no data was added"); } - self.added.sort(); self.added.dedup(); let mut last = (0, 0); let max_subject = self.added.iter().map(|a| a.0).max().unwrap_or(0); let max_index = self.added.iter().map(|a| a.1).max().unwrap_or(0); + let max_object = self.added.iter().map(|a| a.2).max().unwrap_or(0); let subjects_width = calculate_width(max_subject); let index_width = calculate_width(max_index as u64); + let object_width = calculate_width(max_object); - let mut subjects_logarray = - LogArrayBufBuilder::new(buffers.subjects_logarray_buf, subjects_width); - let mut predicates_logarray = LogArrayBufBuilder::new(buffers.index_logarray_buf, index_width); - let mut boundary_bitindex = BitArrayFileBuilder; + let mut subjects_logarray = LogArrayBufBuilder::new(BytesMut::new(), subjects_width); + let mut aj_builder = AdjacencyListBufBuilder::new(index_width); + let mut objects_logarray = LogArrayBufBuilder::new(BytesMut::new(), object_width); + let mut index = 0; for added in self.added { if (added.0, added.1) == last { panic!("multiple indexed properties for same index and node"); } + if added.0 != last.0 { + // we moved on to a next item + index += 1; + } last = (added.0, added.1); subjects_logarray.push(added.0); - predicates_logarray.push(added.1 as u64); + aj_builder.push(index, added.1 as u64); + objects_logarray.push(added.2); + } + + let subjects_buf = subjects_logarray.finalize().freeze(); + let aj_bufs = aj_builder.finalize(); + let objects_buf = objects_logarray.finalize().freeze(); + + IndexPropertyBuffers { + subjects_logarray_buf: subjects_buf, + adjacency_bufs: aj_bufs, + objects_logarray_buf: objects_buf, + } + } +} + +pub struct IndexedPropertyCollection { + subjects: MonotonicLogArray, + adjacencies: AdjacencyList, + objects: LogArray, +} + +impl IndexedPropertyCollection { + pub fn from_buffers(buffers: IndexPropertyBuffers) -> Self { + Self { + subjects: MonotonicLogArray::parse(buffers.subjects_logarray_buf).unwrap(), + adjacencies: AdjacencyList::from_buffers(buffers.adjacency_bufs), + objects: LogArray::parse(buffers.objects_logarray_buf).unwrap(), } } + + pub fn lookup_index(&self, subject: u64, index: usize) -> Option { + if let Some(subject_index) = self.subjects.index_of(subject) { + let offset = self.adjacencies.offset_for(subject_index as u64); + let indexes = self.adjacencies.get(subject_index as u64); + if let Some(index_index) = indexes.index_of(index as u64) { + let total_offset = offset as usize + index_index; + let object = self.objects.entry(total_offset); + + return Some(object); + } + } + + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn build_and_lookup_indexed_property_collection() { + let mut builder = IndexedPropertyBuilder::new(); + builder.add(3, 4, 42); + builder.add(3, 7, 420); + builder.add(5, 1, 21); + let buffers = builder.finalize(); + let collection = IndexedPropertyCollection::from_buffers(buffers); + + assert_eq!(Some(42), collection.lookup_index(3, 4)); + assert_eq!(Some(420), collection.lookup_index(3, 7)); + assert_eq!(Some(21), collection.lookup_index(5, 1)); + assert_eq!(None, collection.lookup_index(5, 2)); + } }