use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::sync::Arc;
use async_lib::AsyncRuntimeManager;
use async_std::sync::Arc as AsyncArc;
use nandoize::{nandoize, PersistableDerive};
use object_lib::allocators::{
bump_allocator::BumpAllocator, persistently_allocatable::PersistentlyAllocatable,
};
use object_lib::collections::{pmap::PHashMap, pvec::PVec};
use object_lib::{IPtr, ObjectId, Persistable};
use object_tracker::ObjectTracker;
use ownership_tracker::OwnershipTracker;
use parking_lot::RwLock;
#[repr(C)]
#[derive(PersistableDerive)]
pub struct SmallStruct {
pub key: u64,
pub data: PVec<u64>,
}
impl SmallStruct {
#[allow(dead_code)]
fn new(key: u64) -> Self {
Self {
key,
data: PVec::new(),
}
}
}
impl PersistentlyAllocatable for SmallStruct {
fn set_allocator(&mut self, allocator: Arc<RwLock<BumpAllocator>>) {
self.data.set_allocator(allocator);
}
fn get_allocator(&self) -> Option<Arc<RwLock<BumpAllocator>>> {
self.data.get_allocator()
}
}
pub fn init_small_struct(object_tracker: &Arc<ObjectTracker>) -> IPtr {
let object = object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), Some(123))
.unwrap();
match object.is_initialized() {
false => {
let object_data = object.allocate::<SmallStruct>().unwrap();
object.set_inner_allocator(object_data);
object_data.key = 42;
object_data.data.resize_to_capacity(4);
let _ = object.bump_version();
}
true => {
let object_data =
unsafe { object.read_into::<SmallStruct>(None).unwrap().as_mut() }.unwrap();
object.set_inner_allocator(object_data);
}
};
object_tracker.push_initial_version(object.id, (&*object).into());
IPtr::new(123, 0, 0)
}
pub fn seed_small_structs(
seed_data: Option<PathBuf>,
object_tracker: Arc<ObjectTracker>,
_ownership_tracker: AsyncArc<&OwnershipTracker>,
async_rt_manager: Arc<AsyncRuntimeManager>,
) {
if seed_data.is_none() {
println!("No seed file provided, skipping");
return;
}
let seed_data_path = seed_data.unwrap();
println!("Seeding local data from {}", seed_data_path.display());
let seed_data_file = File::open(seed_data_path).unwrap();
let reader = BufReader::new(seed_data_file);
async_rt_manager.block_on(async move {
for line_iter in reader.lines() {
let line = line_iter.unwrap();
let line_elems = line.split(";").collect::<Vec<&str>>();
let object_id: ObjectId = line_elems[0].parse::<ObjectId>().unwrap();
let key = line_elems[1].trim().parse::<u64>().unwrap();
let data_len = line_elems[2].trim().parse::<usize>().unwrap();
let _iptr = {
let object = {
object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), Some(object_id))
.unwrap()
};
let object_data = object.allocate::<SmallStruct>().unwrap();
object.set_inner_allocator(object_data);
object_data.data.resize_to_capacity(data_len);
object_data.key = key;
for e in line_elems[3].split(",").collect::<Vec<&str>>() {
let trimmed_elem = e.trim();
if trimmed_elem.len() == 0 || object_data.data.len() == data_len {
break;
}
object_data.data.push(trimmed_elem.parse::<u64>().unwrap());
}
object.flush();
println!("Current object id {}", object.id);
object_tracker.push_initial_version(object.id, (&*object).into());
IPtr::new(object_id, 0, 0)
};
#[cfg(not(feature = "offline"))]
{
_ownership_tracker.mark_owned(_iptr.object_id);
_ownership_tracker.publish_object(&_iptr).await;
}
}
});
}
#[nandoize]
pub fn set_key(v: &mut SmallStruct, k: u64) {
v.key = k;
}
#[nandoize]
pub fn get_key(v: &SmallStruct) -> u64 {
v.key
}
#[nandoize]
pub fn add_elem(v: &mut SmallStruct, e: u64) {
v.data.push(e);
}
#[nandoize]
pub fn print_elems(v: &SmallStruct) {
println!("Len: {}", v.data.len());
for i in &v.data {
print!("{i}, ");
}
print!("\n");
}
#[repr(C)]
#[derive(PersistableDerive)]
pub struct SomeMap {
pub some_value: u64,
pub data: PHashMap<u64, u64>,
}
#[cfg(test)]
mod tests {
use std::sync::{Arc, RwLock};
use nando_lib::nando_manager::NandoManager;
use nando_lib::NandoManagerBase;
use object_lib::IPtr;
use object_lib::ObjectTracker;
use crate::pstructs::SmallStruct;
use crate::pstructs::SomeMap;
#[test]
#[ignore]
fn simple_allocation() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SmallStruct>().unwrap();
vs.key = 42;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.resize_to_capacity(8);
assert!(true);
}
#[test]
#[ignore]
fn simple_extend() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SmallStruct>().unwrap();
vs.key = 42;
vs.some_val = 17;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.resize_to_capacity(2);
vs.data.push(82);
vs.data.push(11);
vs.data.push(12);
assert_eq!(vs.data.len(), 3);
}
#[test]
#[ignore]
fn big_allocation() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SmallStruct>().unwrap();
vs.key = 42;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.resize_to_capacity(10000);
for i in 0..10002 {
vs.data.push(i);
}
assert_eq!(vs.data.len(), 100002);
}
#[test]
#[ignore]
fn pop_empty() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SmallStruct>().unwrap();
vs.key = 42;
vs.some_val = 17;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.resize_to_capacity(2);
assert_eq!(vs.data.pop(), None);
}
#[test]
#[ignore]
fn pop_not_empty() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SmallStruct>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SmallStruct>().unwrap();
vs.key = 42;
vs.some_val = 17;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.resize_to_capacity(2);
vs.data.push(11);
vs.data.push(42);
assert_eq!(vs.data.pop(), Some(42));
}
#[test]
#[ignore]
fn simple_allocation_pmap() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SomeMap>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SomeMap>().unwrap();
vs.some_value = 42;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.with_capacity(8);
vs.data.insert(0, 42);
assert_eq!(vs.data.len(), 1);
assert_eq!(vs.data.contains(0), true);
assert_eq!(vs.data.contains(1), false);
assert_eq!(vs.data.get(0), Some(&42));
}
#[test]
#[ignore]
fn pmap_resize() {
let object_tracker = match ObjectTracker::new(0) {
Some(v) => Arc::new(RwLock::new(v)),
_ => panic!("Failed to init object tracker in test"),
};
let mut object_tracker = object_tracker.write().unwrap();
let obj_lock = object_tracker
.allocate(std::mem::size_of::<SomeMap>(), None)
.unwrap();
let obj = obj_lock.lock();
let mut vs = obj.allocate::<SomeMap>().unwrap();
vs.some_value = 42;
vs.data.set_allocator(Arc::clone(&obj.backing_allocator));
vs.data.with_capacity(2);
vs.data.insert(0, 42);
assert_eq!(vs.data.len(), 1);
assert_eq!(vs.data.contains(0), true);
assert_eq!(vs.data.get(0), Some(&42));
vs.data.insert(1, 42);
vs.data.insert(3, 44);
assert_eq!(vs.data.len(), 3);
assert_eq!(vs.data.contains(0), true);
assert_eq!(vs.data.contains(1), true);
assert_eq!(vs.data.contains(3), true);
assert_eq!(vs.data.contains(4), false);
assert_eq!(vs.data.get(0), Some(&42));
}
}