WS4ZQM4RMIHZ6XZKSDQJGHN5SSSWFL4H236USOPUA33S6RC53RFAC
unsafe {
if r == 0 {
put::<_, _, _, Leaf>(txn, page, mutable, c.cur, k0, v0, 0, 0)
} else {
put::<_, _, _, Internal>(txn, page, mutable, c.cur, k0, v0, l, r)
}
if r == 0 {
put::<_, _, _, Leaf>(txn, page, mutable, c.cur, k0, v0, 0, 0)
} else {
put::<_, _, _, Internal>(txn, page, mutable, c.cur, k0, v0, l, r)
unsafe {
let new = txn.alloc_page()?;
<Page<K, V> as BTreeMutPage<T, K, V>>::init(new);
let s = Internal::offset_slice::<T, K, V>(page);
let hdr = &mut *header_mut(new);
let mut n = 0;
clone::<T, K, V, Internal>(hdr, page, new, s, &mut n);
let b = if Self::is_dirty(page) { 1 } else { 0 };
freed = page.offset | b;
new
}
let mut new = txn.alloc_page()?;
<Page<K, V> as BTreeMutPage<T, K, V>>::init(&mut new);
let s = Internal::offset_slice::<T, K, V>(page.as_page());
let mut n = 0;
clone::<T, K, V, Internal>(page.as_page(), &mut new, s, &mut n);
let b = if Self::is_dirty(page.as_page()) { 1 } else { 0 };
freed = page.offset | b;
new
if Self::is_dirty(page) {
let page = MutPage(page);
unsafe {
let hdr = header_mut(page);
if c.is_leaf {
let n = (&*hdr).n() as usize;
if let Some(f) = fixed_size::<T, K, V>() {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
let off = c.cur * f;
let kv_ptr = page.0.data.add(hdr_size + off);
core::ptr::copy(kv_ptr.add(f), kv_ptr, f * (n - c.cur - 1));
(&mut *hdr).decr(f);
} else {
let ptr = page.0.data.add(HDR + c.cur * 2) as *mut u16;
let kv_ptr = page.0.data.add((*ptr) as usize);
let size = entry_size::<T, K, V>(kv_ptr);
core::ptr::copy(ptr.offset(1), ptr, n - c.cur);
(&mut *hdr).decr(size);
}
} else {
let ptr = page.0.data.add(HDR + c.cur * 8) as *mut u64;
let off = (u64::from_le(*ptr) & 0xfff) as usize;
let kv_ptr = page.0.data.add(off);
let size = entry_size::<T, K, V>(kv_ptr);
core::ptr::copy(ptr.offset(1), ptr, (&*hdr).n() as usize - c.cur);
(&mut *hdr).decr(size);
};
if l > 0 {
assert!(!c.is_leaf);
// Updating the left page if necessary.
let off = (page.0.data.add(HDR) as *mut u64).offset(c.cur as isize - 1);
if Self::is_dirty(page.as_page()) {
let p = page.data;
let mut page: MutPage = unsafe { core::mem::transmute(page) };
let hdr = header_mut(&mut page);
unsafe { if c.is_leaf {
let n = hdr.n() as usize;
if let Some(f) = fixed_size::<T, K, V>() {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
let off = c.cur * f;
let kv_ptr = p.add(hdr_size + off);
core::ptr::copy(kv_ptr.add(f), kv_ptr, f * (n - c.cur - 1));
hdr.decr(f);
} else {
let ptr = p.add(HDR + c.cur * 2) as *mut u16;
let kv_ptr = p.add((*ptr) as usize);
let size = entry_size::<T, K, V>(kv_ptr);
core::ptr::copy(ptr.offset(1), ptr, n - c.cur);
hdr.decr(size);
}
} else {
let ptr = p.add(HDR + c.cur * 8) as *mut u64;
let off = (u64::from_le(*ptr) & 0xfff) as usize;
let kv_ptr = p.add(off);
let size = entry_size::<T, K, V>(kv_ptr);
core::ptr::copy(ptr.offset(1), ptr, (&*hdr).n() as usize - c.cur);
(&mut *hdr).decr(size);
}};
if l > 0 {
assert!(!c.is_leaf);
// Updating the left page if necessary.
unsafe {
let off = (p as *mut u64).offset(c.cur as isize - 1);
unsafe {
return Ok(Op::Put(if let Some((k, v, r)) = m.modified.ins {
Self::replace(
txn,
m.modified.page,
m.modified.mutable,
&m.modified.c1,
&*k,
&*v,
m.modified.l,
r,
)?
} else {
Put::Ok(Ok {
page: Self::del(txn, m.modified.page, &m.modified.c1, m.modified.l)?,
freed: 0,
})
}));
}
return Ok(Op::Put(if let Some((k, v, r)) = m.modified.ins {
Self::replace(
txn,
m.modified.page,
m.modified.mutable,
&m.modified.c1,
&*k,
&*v,
m.modified.l,
r,
)?
} else {
Put::Ok(Ok {
page: Self::del(txn, m.modified.page, &m.modified.c1, m.modified.l)?,
freed: 0,
})
}));
fn first_cursor(p: &crate::Page) -> Self::Cursor {
unsafe {
let hdr = &*header(p);
Cursor {
cur: 0,
total: hdr.n() as usize,
is_leaf: hdr.is_leaf(),
}
fn first_cursor(p: crate::Page) -> Self::Cursor {
let hdr = header(p);
Cursor {
cur: 0,
total: hdr.n() as usize,
is_leaf: hdr.is_leaf(),
fn last_cursor(p: &crate::Page) -> Self::Cursor {
unsafe {
let hdr = &*header(p);
let total = hdr.n() as usize;
Cursor {
cur: total - 1,
total,
is_leaf: hdr.is_leaf(),
}
fn last_cursor(p: crate::Page) -> Self::Cursor {
let hdr = header(p);
let total = hdr.n() as usize;
Cursor {
cur: total - 1,
total,
is_leaf: hdr.is_leaf(),
let off = u64::from_le(*(page.data.add(HDR) as *const u64).add(c.cur));
let (k, v) = read::<T, K, V>(page.data.add((off & 0xfff) as usize));
(k, v, off & !0xfff)
let off = u64::from_le(*(page.data.as_ptr().add(HDR) as *const u64).add(c.cur));
let (k, v) = read::<T, K, V>(page.data.as_ptr().add((off & 0xfff) as usize));
(&*k, &*v, off & !0xfff)
8 + entry_size::<T, K, V>(page.data.add(
(u64::from_le(*(page.data.add(HDR) as *const u64).add(c.cur)) & 0xfff) as usize,
8 + entry_size::<T, K, V>(page.data.as_ptr().add(
(u64::from_le(*(page.data.as_ptr().add(HDR) as *const u64).add(c.cur)) & 0xfff) as usize,
c.is_leaf = hdr.is_leaf();
let lookup = if c.is_leaf {
if fixed_size::<T, K, V>().is_some() {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
let s = core::slice::from_raw_parts(
page.data.add(hdr_size) as *const Tuple<K, V>,
hdr.n() as usize,
);
if let Some(v0) = v0 {
s.binary_search_by(|tup| {
(tup.k.ord(txn), tup.v.ord(txn)).cmp(&(k0.ord(txn), v0.ord(txn)))
})
} else {
s.binary_search_by(|tup| {
(tup.k.ord(txn)).cmp(k0.ord(txn))
})
}
} else {
let s = core::slice::from_raw_parts(
page.data.add(HDR) as *const u16,
hdr.n() as usize,
);
if let Some(v0) = v0 {
s.binary_search_by(|&off| {
let off = u16::from_le(off);
let (k, v) = read::<T, K, V>(page.data.offset(off as isize));
((&*k).ord(txn), (&*v).ord(txn)).cmp(&(k0.ord(txn), v0.ord(txn)))
})
} else {
s.binary_search_by(|&off| {
let off = u16::from_le(off);
let (k, _) = read::<T, K, V>(page.data.offset(off as isize));
((&*k).ord(txn)).cmp(k0.ord(txn))
})
}
}
} else {
let s =
core::slice::from_raw_parts(page.data.add(HDR) as *const u64, hdr.n() as usize);
if let Some(v0) = v0 {
s.binary_search_by(|&off| {
let off = u64::from_le(off) & 0xfff;
let (k, v) = read::<T, K, V>(page.data.offset(off as isize & 0xfff));
((&*k).ord(txn), (&*v).ord(txn)).cmp(&(k0.ord(txn), v0.ord(txn)))
})
} else {
s.binary_search_by(|&off| {
let off = u64::from_le(off) & 0xfff;
let (k, _) = read::<T, K, V>(page.data.offset(off as isize & 0xfff));
((&*k).ord(txn)).cmp(k0.ord(txn))
})
}
};
let off = u64::from_le(*(page.data.add(HDR + n * 8) as *const u64));
Ok(Internal::kv(*page, (off & !0xfff, (off & 0xfff) as u16)))
let off = u64::from_le(*(page.data.as_ptr().add(HDR + n * 8) as *const u64));
Ok(Internal::kv(page, (off & !0xfff, (off & 0xfff) as u16)))
unsafe fn lookup<T, K: Representable<T>, V: Representable<T>>(
txn: &T,
page: crate::Page,
c: &mut Cursor,
k0: &K,
v0: Option<&V>,
) -> Result<usize, usize> {
let hdr = header(page);
c.total = hdr.n() as usize;
c.is_leaf = hdr.is_leaf();
if c.is_leaf {
if fixed_size::<T, K, V>().is_some() {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
let s = core::slice::from_raw_parts(
page.data.as_ptr().add(hdr_size) as *const Tuple<K, V>,
hdr.n() as usize,
);
if let Some(v0) = v0 {
s.binary_search_by(|tup| {
(tup.k.ord(txn), tup.v.ord(txn)).cmp(&(k0.ord(txn), v0.ord(txn)))
})
} else {
s.binary_search_by(|tup| {
(tup.k.ord(txn)).cmp(k0.ord(txn))
})
}
} else {
let s = core::slice::from_raw_parts(
page.data.as_ptr().add(HDR) as *const u16,
hdr.n() as usize,
);
if let Some(v0) = v0 {
s.binary_search_by(|&off| {
let off = u16::from_le(off);
let (k, v) = read::<T, K, V>(page.data.as_ptr().offset(off as isize));
((&*k).ord(txn), (&*v).ord(txn)).cmp(&(k0.ord(txn), v0.ord(txn)))
})
} else {
s.binary_search_by(|&off| {
let off = u16::from_le(off);
let (k, _) = read::<T, K, V>(page.data.as_ptr().offset(off as isize));
((&*k).ord(txn)).cmp(k0.ord(txn))
})
}
}
} else {
let s =
core::slice::from_raw_parts(page.data.as_ptr().add(HDR) as *const u64, hdr.n() as usize);
if let Some(v0) = v0 {
s.binary_search_by(|&off| {
let off = u64::from_le(off) & 0xfff;
let (k, v) = read::<T, K, V>(page.data.as_ptr().offset(off as isize & 0xfff));
((&*k).ord(txn), (&*v).ord(txn)).cmp(&(k0.ord(txn), v0.ord(txn)))
})
} else {
s.binary_search_by(|&off| {
let off = u64::from_le(off) & 0xfff;
let (k, _) = read::<T, K, V>(page.data.as_ptr().offset(off as isize & 0xfff));
((&*k).ord(txn)).cmp(k0.ord(txn))
})
}
}
}
unsafe fn alloc(hdr: &mut Header, size: usize, align: usize) -> u16;
unsafe fn alloc_insert<T, K: Representable<T>, V: Representable<T>>(
hdr: &mut Header,
new: &MutPage,
fn alloc(hdr: &mut Header, size: usize, align: usize) -> u16;
// n = number of items to remove
fn truncate_left<T, K: Representable<T>, V: Representable<T>>(page: &mut MutPage, n: usize);
fn alloc_insert<T, K: Representable<T>, V: Representable<T>>(
new: &mut MutPage,
unsafe fn alloc(hdr: &mut Header, size: usize, align: usize) -> u16 {
fn truncate_left<T, K: Representable<T>, V: Representable<T>>(page: &mut MutPage, n: usize) {
debug!("truncate_left {:?} {:?}", page, n);
if let Some(f) = fixed_size::<T, K, V>() {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
// debug!("{:?} {:?} {:?}", new, hdr.n(), *n);
let hdr_n = header_mut(page).n();
unsafe {
core::ptr::copy(
page.0.data.add(hdr_size + n * f),
page.0.data.add(hdr_size),
n * f,
);
}
debug!("{:?}-{:?}", hdr_n, n);
let hdr = header_mut(page);
hdr.set_n(hdr_n - n as u16);
hdr.left_page = (hdr.left_page() - (n * f) as u64).to_le();
} else {
let hdr_n = header_mut(page).n();
unsafe {
core::ptr::copy(
page.0.data.add(HDR + n * 2),
page.0.data.add(HDR),
n * 2,
);
}
let deleted_offsets = unsafe {
core::slice::from_raw_parts(
page.0.data.add(HDR) as *const u16,
n as usize,
)
};
let deleted_size: u64 = deleted_offsets.iter().map(|&off| {
2 + unsafe { entry_size::<T, K, V>(page.0.data.add(off as usize)) } as u64
}).sum();
let hdr = header_mut(page);
hdr.set_n(hdr_n - n as u16);
hdr.left_page = (hdr.left_page() - deleted_size).to_le();
}
}
fn alloc(hdr: &mut Header, size: usize, align: usize) -> u16 {
core::ptr::copy(
new.0.data.add(hdr_size + (*n as usize) * f),
new.0.data.add(hdr_size + (*n as usize) * f + f),
(hdr.n() as usize - (*n as usize)) * f,
);
let hdr_n = header_mut(new).n();
unsafe {
core::ptr::copy(
new.0.data.add(hdr_size + (*n as usize) * f),
new.0.data.add(hdr_size + (*n as usize) * f + f),
(hdr_n as usize - (*n as usize)) * f,
);
}
let hdr = header_mut(new);
let off_new = Self::alloc(&mut *hdr, size, K::ALIGN);
core::ptr::copy(
new.0.data.add(HDR + (*n as usize) * 2),
new.0.data.add(HDR + (*n as usize) * 2 + 2),
(hdr.n() as usize - (*n as usize)) * 2,
);
Self::set_offset(*new, *n, 0, off_new);
let (hdr_n, off_new) = {
let hdr = header_mut(new);
(hdr.n(), Self::alloc(&mut *hdr, 2+size, K::ALIGN))
};
unsafe {
core::ptr::copy(
new.0.data.add(HDR + (*n as usize) * 2),
new.0.data.add(HDR + (*n as usize) * 2 + 2),
(hdr_n as usize - (*n as usize)) * 2,
);
}
Self::set_offset(new, *n, 0, off_new);
unsafe fn set_offset(new: MutPage, n: isize, _: u64, off: u16) {
let ptr = new.0.data.offset(HDR as isize + n * 2) as *mut u16;
*ptr = off.to_le();
fn set_offset(new: &mut MutPage, n: isize, _: u64, off: u16) {
unsafe {
let ptr = new.0.data.offset(HDR as isize + n * 2) as *mut u16;
*ptr = off.to_le();
}
unsafe fn alloc(hdr: &mut Header, size: usize, align: usize) -> u16 {
fn truncate_left<T, K: Representable<T>, V: Representable<T>>(page: &mut MutPage, n: usize) {
// The following line copies the left child of the last entry
// (hence the `- 8` and `- 1`)
unsafe {
core::ptr::copy(
page.0.data.add(HDR + (n - 1) * 8),
page.0.data.add(HDR - 8),
(n + 1) * 8,
);
}
let hdr_n = header_mut(page).n();
let size = if let Some(f) = fixed_size::<T, K, V>() {
((8 + f) * (hdr_n as usize - n)) as u64
} else {
let offsets = unsafe {
core::slice::from_raw_parts(
page.0.data.add(HDR + n * 8) as *const u16,
hdr_n as usize - n as usize,
)
};
offsets.iter().map(|&off| {
8 + unsafe { entry_size::<T, K, V>(page.0.data.add(off as usize)) } as u64
}).sum()
};
let hdr = header_mut(page);
hdr.set_n(hdr_n - n as u16);
hdr.left_page = ((hdr.left_page() & !0xfff) | size).to_le();
}
fn alloc(hdr: &mut Header, size: usize, align: usize) -> u16 {
debug!("data = {:?}, size = {:?}", hdr.data, size);
let off_new = Self::alloc(&mut *hdr, size, K::ALIGN.max(V::ALIGN));
core::ptr::copy(
new.0.data.add(HDR + (*n as usize) * 8),
new.0.data.add(HDR + (*n as usize) * 8 + 8),
(hdr.n() as usize - (*n as usize)) * 8,
);
Self::set_offset(*new, *n, r, off_new);
let (hdr_n, off_new) = {
let hdr = header_mut(new);
(hdr.n(), Self::alloc(&mut *hdr, size, K::ALIGN.max(V::ALIGN)))
};
unsafe {
core::ptr::copy(
new.0.data.add(HDR + (*n as usize) * 8),
new.0.data.add(HDR + (*n as usize) * 8 + 8),
(hdr_n as usize - (*n as usize)) * 8,
);
}
Self::set_offset(new, *n, r, off_new);
unsafe fn set_offset(new: MutPage, n: isize, r: u64, off: u16) {
let ptr = new.0.data.offset(HDR as isize + n * 8) as *mut u64;
*ptr = (r | off as u64).to_le();
fn set_offset(new: &mut MutPage, n: isize, r: u64, off: u16) {
unsafe {
let ptr = new.0.data.offset(HDR as isize + n * 8) as *mut u64;
*ptr = (r | off as u64).to_le();
}
unsafe fn set_right_child(page: MutPage, n: isize, r: u64) {
let ptr = page.0.data.offset(HDR as isize + n * 8) as *mut u64;
let off = u64::from_le(*ptr) & 0xfff;
*ptr = (r | off as u64).to_le();
fn set_right_child(page: &mut MutPage, n: isize, r: u64) {
unsafe {
let ptr = page.0.data.offset(HDR as isize + n * 8) as *mut u64;
let off = u64::from_le(*ptr) & 0xfff;
*ptr = (r | off as u64).to_le();
}
let hdr = &*header(&page);
Offsets::Slice(core::slice::from_raw_parts(
page.data.add(HDR) as *const InternalOffset,
hdr.n() as usize,
))
let hdr = header(page);
unsafe {
Offsets::Slice(core::slice::from_raw_parts(
page.data.as_ptr().add(HDR) as *const InternalOffset,
hdr.n() as usize,
))
}
let hdr = &mut *header_mut(new);
let mut l = <Page<K, V>>::left_child(&m.page, &m.c0);
while let Some((k, v, r)) = <Page<K, V>>::next(&m.page, &mut m.c0) {
alloc::<_, _, _, L>(hdr, new, k, v, l, r, n);
let mut l = <Page<K, V>>::left_child(m.page.as_page(), &m.c0);
while let Some((k, v, r)) = <Page<K, V>>::next(m.page.as_page(), &mut m.c0) {
alloc::<_, _, _, L>(new, k, v, l, r, n);
modify::<_, _, _, L>(new, m.modified, &mut n);
let mut rc = <Page<K, V>>::first_cursor(&m.other);
let l = <Page<K, V>>::left_child(&m.other, &rc);
alloc::<_, _, _, L>(hdr, new, &*m.mid.0, &*m.mid.1, 0, l, &mut n);
while let Some((k, v, r)) = <Page<K, V>>::next(&m.other, &mut rc) {
alloc::<_, _, _, L>(hdr, new, k, v, 0, r, &mut n);
modify::<_, _, _, L>(new, &mut m.modified, &mut n);
let mut rc = <Page<K, V>>::first_cursor(m.other.as_page());
let l = <Page<K, V>>::left_child(m.other.as_page(), &rc);
alloc::<_, _, _, L>(new, &*m.mid.0, &*m.mid.1, 0, l, &mut n);
while let Some((k, v, r)) = <Page<K, V>>::next(m.other.as_page(), &mut rc) {
alloc::<_, _, _, L>(new, k, v, 0, r, &mut n);
let mut rc = <Page<K, V>>::first_cursor(&m.other);
let mut l = <Page<K, V>>::left_child(&m.other, &rc);
while let Some((k, v, r)) = <Page<K, V>>::next(&m.other, &mut rc) {
alloc::<_, _, _, L>(hdr, new, k, v, l, r, &mut n);
let mut rc = <Page<K, V>>::first_cursor(m.other.as_page());
let mut l = <Page<K, V>>::left_child(m.other.as_page(), &rc);
while let Some((k, v, r)) = <Page<K, V>>::next(m.other.as_page(), &mut rc) {
alloc::<_, _, _, L>(new, k, v, l, r, &mut n);
let rc = <Page<K, V>>::first_cursor(&m.other);
let rl = <Page<K, V>>::left_child(&m.other, &rc);
let (k, v, r) = <Page<K, V>>::unchecked_current(&m.other, &rc);
let rc = <Page<K, V>>::first_cursor(m.other.as_page());
let rl = <Page<K, V>>::left_child(m.other.as_page(), &rc);
let (k, v, r) = unsafe { <Page<K, V>>::unchecked_current(m.other.as_page(), &rc) };
let new = txn.alloc_page()?;
<Page<K, V> as BTreeMutPage<T, K, V>>::init(new);
let s = L::offset_slice::<T, K, V>(m.modified.page);
let hdr = &mut *header_mut(new);
let mut new = txn.alloc_page()?;
<Page<K, V> as BTreeMutPage<T, K, V>>::init(&mut new);
let s = L::offset_slice::<T, K, V>(m.modified.page.as_page());
clone::<T, K, V, L>(hdr, m.modified.page, new, s, &mut n);
alloc::<T, K, V, L>(hdr, new, &*m.mid.0, &*m.mid.1, 0, rl, &mut n);
let b = if hdr.is_dirty() { 1 } else { 0 };
clone::<T, K, V, L>(m.modified.page.as_page(), &mut new, s, &mut n);
alloc::<T, K, V, L>(&mut new, m.mid.0, m.mid.1, 0, rl, &mut n);
let b = if header(m.modified.page.as_page()).is_dirty() { 1 } else { 0 };
let off = u16::from_le(off);
let ptr = page.data.add(off as usize);
let size = entry_size::<T, K, V>(ptr);
let off_new = L::alloc(&mut *hdr, size, K::ALIGN);
core::ptr::copy_nonoverlapping(ptr, new.0.data.offset(off_new as isize), size);
L::set_offset(new, *n, r, off_new);
debug!("clone: {:?} {:?}", r, off);
unsafe {
let ptr = page.data.as_ptr().add(off as usize);
let size = entry_size::<T, K, V>(ptr);
debug!("size: {:?}", size);
let hdr = header_mut(new);
let off_new = L::alloc(hdr, size, K::ALIGN);
debug!("off_new: {:?}", off_new);
core::ptr::copy_nonoverlapping(ptr, new.0.data.offset(off_new as isize), size);
L::set_offset(new, *n, r, off_new);
}
let ptr = page.data.add(header_size + off * size);
let new_ptr = new.0.data.add(header_size + (*n as usize) * size);
core::ptr::copy_nonoverlapping(ptr, new_ptr, size);
hdr.set_n(hdr.n() + 1);
hdr.left_page = (hdr.left_page() + size as u64).to_le();
unsafe {
let ptr = page.data.as_ptr().add(header_size + off * size);
let new_ptr = new.0.data.add(header_size + (*n as usize) * size);
core::ptr::copy_nonoverlapping(ptr, new_ptr, size);
}
let off_new = L::alloc_insert::<T, K, V>(hdr, &new, n, size, r);
let new_ptr = new.0.data.add(off_new as usize);
core::ptr::copy_nonoverlapping(k0, new_ptr as *mut K, 1);
let ks = k0.size();
let v_ptr = new_ptr.add((ks + V::ALIGN - 1) & !(V::ALIGN - 1));
core::ptr::copy_nonoverlapping(v0, v_ptr as *mut V, 1);
let off_new = L::alloc_insert::<T, K, V>(new, n, size, r);
unsafe {
let new_ptr = new.0.data.add(off_new as usize);
core::ptr::copy_nonoverlapping(k0, new_ptr as *mut K, 1);
let ks = k0.size();
let v_ptr = new_ptr.add((ks + V::ALIGN - 1) & !(V::ALIGN - 1));
core::ptr::copy_nonoverlapping(v0, v_ptr as *mut V, 1);
}
let hdr = &*header(&page);
if mutable && hdr.is_dirty() && L::can_alloc::<T, K, V>(&*header(&page), size) {
let page = MutPage(page);
let hdr = &mut *header_mut(page);
let hdr = header(page.as_page());
let is_dirty = hdr.is_dirty();
debug!("put {:?} {:?} {:?}", u, mutable, is_dirty);
if mutable && is_dirty && L::can_alloc::<T, K, V>(header(page.as_page()), size) {
debug!("can alloc");
let mut page = unsafe { core::mem::transmute(page) };
let new = txn.alloc_page()?;
<Page<K, V> as BTreeMutPage<T, K, V>>::init(new);
let s = L::offset_slice::<T, K, V>(page);
let mut new = txn.alloc_page()?;
debug!("can compact: {:?}", new);
<Page<K, V> as BTreeMutPage<T, K, V>>::init(&mut new);
L::set_right_child(&mut new, -1, hdr.left_page & !0xfff);
let s = L::offset_slice::<T, K, V>(page.as_page());
clone::<T, K, V, L>(hdr, page, new, s0, &mut n);
alloc::<T, K, V, L>(hdr, new, k0, v0, l, r, &mut n);
clone::<T, K, V, L>(hdr, page, new, s1, &mut n);
let b0 = if hdr.is_dirty() { 1 } else { 0 };
clone::<T, K, V, L>(page.as_page(), &mut new, s0, &mut n);
alloc::<T, K, V, L>(&mut new, k0, v0, l, r, &mut n);
clone::<T, K, V, L>(page.as_page(), &mut new, s1, &mut n);
let b0 = if is_dirty { 1 } else { 0 };
if mutable && hdr.is_dirty() && u >= k as usize {
// (k0, v0) is to be inserted on the right-hand side of
// the split, hence we don't have to clone the left-hand
// side, we can just truncate it.
let hdr = &mut *header_mut(MutPage(page));
left = MutPage(page);
hdr.set_n(k);
hdr.decr((n - 1 - k) as usize * size);
if u >= k as usize {
if mutable && hdr.is_dirty() {
debug!("mutable dirty {:?} >= {:?}", u, k);
// (k0, v0) is to be inserted on the right-hand side of
// the split, hence we don't have to clone the left-hand
// side, we can just truncate it.
left = unsafe { core::mem::transmute(page) };
let hdr = header_mut(&mut left);
hdr.set_n(k);
hdr.decr((n - 1 - k) as usize * size);
} else {
left = txn.alloc_page()?;
debug!("immutable {:?} >= {:?}", u, k);
let mut n = 0;
clone::<T, K, V, L>(page.as_page(), &mut left, s0, &mut n);
freed = page.offset | page_is_dirty
}
// If we are here, u >= k, i.e. the insertion is in the right-hand
// side of the split.
let mut n = 0;
let mut right = txn.alloc_page()?;
<Page<K, V> as BTreeMutPage<T, K, V>>::init(&mut right);
if u > k as usize {
let kk = u as usize - k as usize - 1;
let (s1a, s1b) = s1.split_at(kk);
L::set_right_child(&mut right, -1, mid_child);
clone::<T, K, V, L>(page.as_page(), &mut right, s1a, &mut n);
alloc::<T, K, V, L>(&mut right, k0, v0, l, r, &mut n);
clone::<T, K, V, L>(page.as_page(), &mut right, s1b, &mut n);
} else {
// Insertion in the middle.
L::set_right_child(&mut right, -1, mid_child);
clone::<T, K, V, L>(page.as_page(), &mut right, s1, &mut n);
}
Ok(Put::Split {
split_key,
split_value,
left,
right,
freed,
})
<Page<K, V> as BTreeMutPage<T, K, V>>::init(left);
if u < k as usize {
let mut n = 0;
let hdr = &mut *header_mut(left);
// debug!("{:?} {:?}", u, k);
let (s0a, s0b) = s1.split_at(k as usize - u as usize);
clone::<T, K, V, L>(hdr, page, left, s0a, &mut n);
alloc::<T, K, V, L>(hdr, left, k0, v0, r, l, &mut n);
clone::<T, K, V, L>(hdr, page, left, s0b, &mut n);
let hdr = &mut *header_mut(right);
let mut n = 0;
L::set_right_child(right, -1, mid_child);
clone::<T, K, V, L>(hdr, page, right, s1, &mut n);
return Ok(Put::Split {
split_key,
split_value,
left,
right,
freed: page.offset | page_is_dirty,
});
<Page<K, V> as BTreeMutPage<T, K, V>>::init(&mut left);
debug!("{:?} < {:?}", u, k);
let mut n = 0;
let mid = k as usize - u as usize;
let (s0a, s0b) = s0.split_at(mid);
clone::<T, K, V, L>(page.as_page(), &mut left, s0a, &mut n);
alloc::<T, K, V, L>(&mut left, k0, v0, r, l, &mut n);
clone::<T, K, V, L>(page.as_page(), &mut left, s0b, &mut n);
let mut right: MutPage;
let freed;
if mutable && hdr.is_dirty() {
right = unsafe { core::mem::transmute(page) };
L::truncate_left::<T, K, V>(&mut right, k as usize);
freed = 0;
// If we are here, u > k, i.e. the insertion is in the right-hand
// side of the split.
let hdr = &mut *header_mut(right);
let mut n = 0;
let kk = u as usize - k as usize;
let (s1a, s1b) = if kk < s1.len() {
s1.split_at(kk)
} else {
(s1, Offsets::Slice(&[][..]))
};
L::set_right_child(right, -1, mid_child);
clone::<T, K, V, L>(hdr, page, right, s1a, &mut n);
alloc::<T, K, V, L>(hdr, right, k0, v0, l, r, &mut n);
clone::<T, K, V, L>(hdr, page, right, s1b, &mut n);
Ok(Put::Split {
split_key,
split_value,
left,
right,
freed,
})
fn first_cursor(p: &Page) -> Self::Cursor;
fn last_cursor(p: &Page) -> Self::Cursor;
fn next<'b>(p: &Page, c: &mut Self::Cursor) -> Option<(&'b mut K, &'b mut V, u64)> {
unsafe {
if let Some((k, v, r)) = Self::current(p, c) {
Self::move_next(p, c);
Some((&mut *k, &mut *v, r))
} else {
None
}
fn first_cursor(p: Page) -> Self::Cursor;
fn last_cursor(p: Page) -> Self::Cursor;
fn next<'b>(p: Page<'b>, c: &mut Self::Cursor) -> Option<(&'b K, &'b V, u64)> {
if let Some((k, v, r)) = Self::current(p, c) {
Self::move_next(p, c);
Some((k, v, r))
} else {
None
fn move_next<'b>(p: &Page, c: &mut Self::Cursor) -> bool;
unsafe fn unchecked_current(p: &Page, c: &Self::Cursor) -> (*mut K, *mut V, u64);
unsafe fn current(p: &Page, c: &Self::Cursor) -> Option<(*mut K, *mut V, u64)> {
fn prev<'b>(p: Page<'b>, c: &mut Self::Cursor) -> Option<(&'b K, &'b V, u64)> {
if Self::move_prev(p, c) {
Self::current(p, c)
} else {
None
}
}
fn move_next(p: Page, c: &mut Self::Cursor) -> bool;
fn move_prev(p: Page, c: &mut Self::Cursor) -> bool;
unsafe fn unchecked_current<'a>(p: Page<'a>, c: &Self::Cursor) -> (&'a K, &'a V, u64);
fn current<'a>(p: Page<'a>, c: &Self::Cursor) -> Option<(&'a K, &'a V, u64)> {
unsafe fn unchecked_current_ptr(p: &Page, c: &Self::Cursor) -> *mut u8;
fn current_size(p: &Page, c: &Self::Cursor) -> usize;
fn left_child(p: &Page, c: &Self::Cursor) -> u64;
fn right_child(p: &Page, c: &Self::Cursor) -> u64;
unsafe fn unchecked_current_ptr(p: Page, c: &Self::Cursor) -> *const u8;
fn current_size(p: Page, c: &Self::Cursor) -> usize;
fn left_child(p: Page, c: &Self::Cursor) -> u64;
fn right_child(p: Page, c: &Self::Cursor) -> u64;
) -> Result<(&'a mut K, &'a mut V, u64), usize>;
fn split_at(p: &Page, c: &Self::Cursor) -> (Self::Cursor, Self::Cursor);
fn is_empty(p: &Page, c: &Self::Cursor) -> bool;
) -> Result<(&'a K, &'a V, u64), usize>;
fn split_at(p: Page, c: &Self::Cursor) -> (Self::Cursor, Self::Cursor);
fn is_empty(p: Page, c: &Self::Cursor) -> bool;
unsafe {
if let Some((k, v, r)) = m.ins {
if m.skip_first {
Self::replace(txn, m.page, m.mutable, &m.c1, &*k, &*v, m.l, r)
} else {
Self::put(txn, m.page, m.mutable, &m.c1, &*k, &*v, m.l, r)
}
if let Some((k, v, r)) = m.ins {
if m.skip_first {
Self::replace(txn, m.page, m.mutable, &m.c1, &*k, &*v, m.l, r)
let ref curs = cursor.current();
let c = curs.cursor.as_ref().unwrap();
if cursor.pointer == p0 {
let other = txn.load_page(P::left_child(&curs.page, c))?;
let c = curs.cursor.as_mut().unwrap();
if let Some(curs0) = curs0 {
let other = txn.load_page(P::left_child(curs.page.as_page(), c))?;
let (k, v, r) = unsafe { P::unchecked_current(&curs.page, c) };
let mut mod_is_left = true;
let (k, v, r) = if let Some(x) = P::current(curs.page.as_page(), c) {
x
} else {
mod_is_left = false;
let (k, v, _) = P::prev(curs.page.as_page(), c).unwrap();
let l = P::left_child(curs.page.as_page(), c);
debug!("prev: {:?}", l);
(k, v, l)
};
unsafe {
*self.stack.get_unchecked_mut(self.pointer) = MaybeUninit::new(PageCursor {
page: txn.load_page(next_page)?,
cursor: None,
});
}
debug!("p+ = {:?}", self.pointer);
self.stack[self.pointer] = MaybeUninit::new(PageCursor {
page: txn.load_page(next_page)?,
cursor: None,
});
#[derive(Eq, PartialEq, PartialOrd, Ord)]
struct A<T>([u64; 100], std::marker::PhantomData<T>);
impl<T> std::fmt::Debug for A<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "A(…)")?;
Ok(())
}
}
impl<T> Representable<T> for A<T> {
type PageOffsets = core::iter::Empty<u64>;
fn page_offsets(&self) -> Self::PageOffsets {
core::iter::empty()
}
const ALIGN: usize = core::mem::align_of::<Self>();
const SIZE: Option<usize> = Some(core::mem::size_of::<Self>());
type Ord = [u64; 100];
fn ord(&self, _: &T) -> &Self::Ord {
&self.0
}
fn size(&self) -> usize {
core::mem::size_of::<Self>()
}
}
type T<'a> = MutTxn<&'a Env<Exclusive>, ()>;
for i in 0..n {
debug!("put {:?}", i);
put(&mut txn, &mut db, &((i * i) % 1_000_000), &(i * i * i)).unwrap();
}
let i = 500;
debug!("deleting {:?}", (i*i)%1_000_000);
del(&mut txn, &mut db, &((i * i) % 1_000_000), None).unwrap();
debug::debug(&txn, &db, "debug", true);
/*
if let Some(page) = self.free_owned_pages.pop() {
let page = MutPage(Page {
data: unsafe { self.env.borrow().find_offset(page) },
offset: page,
});
self.occupied_owned_pages.push(page);
if let Some(offset) = self.free_owned_pages.pop() {
let data = unsafe { self.env.borrow().find_offset(offset) };
let page = MutPage(CowPage { data, offset });
self.occupied_owned_pages
.push(MutPage(CowPage { data, offset }));
if let Some(page) = self.free_pages_pop()? {
let page = MutPage(Page {
data: unsafe { self.env.borrow().find_offset(page) },
offset: page,
});
self.occupied_owned_pages.push(page);
if let Some(offset) = self.free_pages_pop()? {
let data = unsafe { self.env.borrow().find_offset(offset) };
let page = MutPage(CowPage { data, offset });
self.occupied_owned_pages
.push(MutPage(CowPage { offset, data }));
if let Some((rc, ())) = curs.next(self)? {
let off_ = *rc & !0xfff;
if off_ == off {
let r = *rc & 0xfff;
if r > 2 {
*rc = off_ | (r - 1);
} else {
btree::del(self, &mut rc_, rc, None)?;
}
self.rc = Some(rc_);
return Ok(());
let rc = if let Some((rc, ())) = curs.next(self)? {
if *rc & !0xfff == off {
*rc
} else {
1
if let Some((rc, _)) = curs.set(self, Some((&off, None)))? {
let off_ = *rc & !0xfff;
if off_ == off {
let r = *rc & 0xfff;
if r > 2 {
*rc = off_ | (r - 1);
self.rc = Some(rc_);
return Ok(());
} else {
rc_del = *rc;
}
curs.set(self, Some((&off, None)))?;
let rc = if let Some((rc, ())) = curs.next(self)? {
if *rc & !0xfff == off {
*rc
} else {
1
}
} else {
1
};
if rc & 0xfff >= 2 {
btree::del(self, &mut rc_, &rc, None)?;
if rc > 2 {
btree::put(self, &mut rc_, &(rc - 1), &())?;
if let Some((rc, _)) = curs.set(self, Some((&off, None)))? {
let off_ = *rc & !0xfff;
if off_ == off {
let r = *rc & 0xfff;
*rc = off_ | (r + 1);
let rc = if let Some((rc, _)) = curs.set(self, Some((&off, None)))? {
if *rc & !0xfff == off {
*rc & 0xfff