Skip to content

Commit

Permalink
first implementation of indexed properties
Browse files Browse the repository at this point in the history
  • Loading branch information
matko committed Sep 15, 2023
1 parent b0e97d2 commit 9817e20
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 21 deletions.
5 changes: 3 additions & 2 deletions src/structure/adjacencylist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand All @@ -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 {
Expand Down Expand Up @@ -439,6 +439,7 @@ impl AdjacencyListBufBuilder {
}
}

#[derive(Clone)]
pub struct AdjacencyListBuffers {
nums: Bytes,
bits: Bytes,
Expand Down
106 changes: 87 additions & 19 deletions src/structure/indexed_property.rs
Original file line number Diff line number Diff line change
@@ -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<B: BufMut>(mut self, buffers: &mut IndexPropertyBuilderBuffers<B>) {
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<u64> {
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));
}
}

0 comments on commit 9817e20

Please sign in to comment.