Fix issues with jemalloc panic, mapped inserts

- `jemalloc` needs nonzero layout
- mapped inserts erroneously expected order
next
Sayan Nandan 8 months ago
parent e65165ded3
commit 2d2ef40b0b
No known key found for this signature in database
GPG Key ID: 0EBD769024B24F0A

@ -33,7 +33,7 @@ use crate::engine::{
},
error::{QueryError, QueryResult},
fractal::GlobalInstanceLike,
idx::{IndexBaseSpec, MTIndex, STIndex, STIndexSeq},
idx::{IndexBaseSpec, MTIndex, STIndex, STIndexExt, STIndexSeq},
net::protocol::Response,
ql::dml::ins::{InsertData, InsertStatement},
sync::atm::cpin,
@ -99,20 +99,27 @@ fn prepare_insert(
}
InsertData::Map(map) => {
let mut inserted = 0;
let mut iter = fields.st_iter_kv().zip(map.into_iter());
while (iter.len() != 0) & (okay) {
let ((model_field_key, model_field_spec), (this_field_key, mut this_field_data)) = unsafe {
// UNSAFE(@ohsayan): safe because of loop invariant
iter.next().unwrap_unchecked()
let mut map = map.into_iter();
while (map.len() != 0) & okay {
let (field_id, mut data) = unsafe {
// UNSAFE(@ohsayan): loop precondition
map.next().unwrap_unchecked()
};
okay &= model_field_spec.vt_data_fpath(&mut this_field_data);
okay &= model_field_key.as_str() == this_field_key.as_str();
let (spec_field_name, spec_field) =
match fields.stext_get_key_value(field_id.as_str()) {
Some(f) => f,
None => {
okay = false;
break;
}
};
okay &= spec_field.vt_data_fpath(&mut data);
prepared_data.st_insert(
unsafe {
// UNSAFE(@ohsayan): the model is right here. it saves us the work!
model_field_key.clone()
// UNSAFE(@ohsayan): as long as model lives, we're good
spec_field_name.clone()
},
this_field_data,
data,
);
inserted += 1;
}

@ -379,3 +379,19 @@ fn check_pk_extremes() {
assert_eq!(d2, Lit::new_uint(u64::MAX));
assert_eq!(d1.uint().unwrap(), u64::MAX);
}
#[test]
fn empty_slice() {
// bin
let pk1 = PrimaryIndexKey::try_from_dc(Datacell::from(Lit::new_bin(b""))).unwrap();
let pk1_ = PrimaryIndexKey::try_from_dc(Datacell::from(Lit::new_bin(b""))).unwrap();
assert_eq!(pk1, Lit::new_bin(b""));
assert_eq!(pk1, pk1_);
drop((pk1, pk1_));
// str
let pk2 = PrimaryIndexKey::try_from_dc(Datacell::from(Lit::new_str(""))).unwrap();
let pk2_ = PrimaryIndexKey::try_from_dc(Datacell::from(Lit::new_str(""))).unwrap();
assert_eq!(pk2, Lit::new_str(""));
assert_eq!(pk2, pk2_);
drop((pk2, pk2_));
}

@ -553,10 +553,20 @@ impl<'a> Clone for VirtualDatacell<'a> {
}
#[test]
fn virtual_dc_damn() {
fn vdc_check() {
let dc = Lit::new_str("hello, world");
assert_eq!(
VirtualDatacell::new(dc, TagUnique::Str),
Datacell::from("hello, world")
);
}
#[test]
fn empty_slice() {
let dc1 = Datacell::from(Lit::new_bin(b""));
assert_eq!(dc1, Datacell::new_bin(b"".to_vec().into_boxed_slice()));
drop(dc1);
let dc2 = Datacell::from(Lit::new_str(""));
assert_eq!(dc2, Datacell::new_str("".into()));
drop(dc2);
}

@ -131,8 +131,8 @@ impl<'a> Lit<'a> {
}
}
#[allow(unused)]
impl<'a> Lit<'a> {
#[allow(unused)]
/// Attempt to read a binary value
pub fn try_bin(&self) -> Option<&'a [u8]> {
(self.tag.tag_class() == TagClass::Bin).then(|| unsafe {
@ -140,6 +140,7 @@ impl<'a> Lit<'a> {
self.bin()
})
}
#[allow(unused)]
/// Attempt to read a string value
pub fn try_str(&self) -> Option<&'a str> {
(self.tag.tag_class() == TagClass::Str).then(|| unsafe {

@ -325,6 +325,13 @@ pub trait STIndex<K: ?Sized, V>: IndexBaseSpec {
fn st_iter_value<'a>(&'a self) -> Self::IterValue<'a>;
}
pub trait STIndexExt<K, V>: STIndex<K, V> {
fn stext_get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where
K: AsKey + Borrow<Q>,
Q: ?Sized + AsKey;
}
pub trait STIndexSeq<K, V>: STIndex<K, V> {
/// An ordered iterator over the keys and values
type IterOrdKV<'a>: Iterator<Item = (&'a K, &'a V)> + DoubleEndedIterator<Item = (&'a K, &'a V)>

@ -35,7 +35,9 @@ use {
IndexSTSeqDllIterUnordKV, IndexSTSeqDllIterUnordKey, IndexSTSeqDllIterUnordValue,
},
},
super::{AsKey, AsKeyClone, AsValue, AsValueClone, IndexBaseSpec, STIndex, STIndexSeq},
super::{
AsKey, AsKeyClone, AsValue, AsValueClone, IndexBaseSpec, STIndex, STIndexExt, STIndexSeq,
},
crate::engine::mem::StatelessLen,
std::{
alloc::{alloc as std_alloc, dealloc as std_dealloc, Layout},
@ -400,6 +402,25 @@ impl<K: AsKey, V: AsValue, C: Config<K, V>> IndexSTSeqDll<K, V, C> {
&(e.as_ref()).read_value().v
})
}
fn _get_entry<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
where
K: Borrow<Q>,
Q: AsKey,
{
self.m
.get(unsafe {
// UNSAFE(@ohsayan): ref with correct bounds
IndexSTSeqDllQref::from_ref(k)
})
.map(|e| unsafe {
/*
UNSAFE(@ohsayan): immutable ref so neither key nor value are moving and
aliasing is satisifed
*/
let e = e.as_ref();
(&e.k, &e.v)
})
}
fn _get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
@ -707,6 +728,21 @@ where
}
}
impl<K, V, C> STIndexExt<K, V> for IndexSTSeqDll<K, V, C>
where
K: AsKey,
V: AsValue,
C: Config<K, V>,
{
fn stext_get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where
K: AsKey + Borrow<Q>,
Q: ?Sized + AsKey,
{
self._get_entry(k)
}
}
impl<K, V, C> STIndexSeq<K, V> for IndexSTSeqDll<K, V, C>
where
K: AsKey,

@ -51,7 +51,9 @@ pub use {
use std::alloc::{self, Layout};
pub unsafe fn dealloc_array<T>(ptr: *mut T, l: usize) {
alloc::dealloc(ptr as *mut u8, Layout::array::<T>(l).unwrap_unchecked())
if l != 0 {
alloc::dealloc(ptr as *mut u8, Layout::array::<T>(l).unwrap_unchecked())
}
}
/// Native double pointer width (note, native != arch native, but host native)

Loading…
Cancel
Save