73Z2UB3JGRLFNFORE7D64O4IHIFSZASD4G4FLJ4FJLHANT75MGIAC
7WJNSPEWJSJROOYHU6QROWPUZ6WNIOUG2BPSOPDPCK6RG2NQU6OQC
Q7DRIBBRE4MNG4NP3PVIXAJF5PQYLFWYIVK2O4VVLEO6XY3BOSFQC
W26CFMAQOXMUK4ZOJMAN4SMBXMWFQHO7HCTEVW73FQSRMJZFGJIQC
OFINGD26ZWCRDVVDI2ZIBLMHXKEMJA6MRNLANJYUHQPIJLPA7J2AC
OP6SVMOD2GTQ7VNJ4E5KYFG4MIYA7HBMXJTADALMZH4PY7OQRMZQC
WS4ZQM4RMIHZ6XZKSDQJGHN5SSSWFL4H236USOPUA33S6RC53RFAC
H3FVSQIQGFCFKCPXVOSFHP4OSUOBBURJESCZNGQTNDAAD3WQSBEQC
APPY2E7M5NHNC6MFYXSVEKJVAILK7YAZVTVE3W75EK2JNFVS3XBQC
LROAI3NBBSCU4T2YA6EHJYKKKL75AU5A7C7WIRCGIQ56S6HPLRXQC
6UVFCERMGSGNRWCVC3GWO5HWV6MSWE433DXBJVC7KRPP6LLJLCSQC
XEU2QVLCHPYOOD4TQIPEEVYOVSFMKFPLJYWEJYXYJAZ7S54KWDZAC
KX3WVNZW5KHVEH6EOQTZ4RBEFFJ3SGF5I467X3JWZ74PURRK4HVAC
QEUTVAZ4F4EJXRDMWDMYXF6XEDMX7YPVG4IIXEKPIR3K54E5W5OAC
OTWDDJE7TTE73D6BGF4ZN6BH2NFUFLPME2VJ3CPALH463UGWLEIQC
X3QVVQIS7B7L3XYZAWL3OOBUXOJ6RMOKQ45YMLLGAHYPEEKZ45ZAC
DV4A2LR7Q5LAEGAQHLO34PZCHGJUHPAMRZFGT7GUFNKVQKPJNOYQC
EAAYH6BQWDK52EC5RG3BEZQU3FJPN5RRRN4U5KDKDVPKXBVJMNDAC
T73WR2BX2QDQ6APOREBXUKNH52FDLJNBGWPQUYB2TAF2PT7XCL2AC
KM3JAFGPFV7MP7M2LJIYRVAUTU646B3IRXADTRZKOU2RF7LUB62QC
fn size(m: &ModifiedPage<K, V, Self>) -> usize {
let mut occupied = {
let hdr = header(m.page.as_page());
(hdr.left_page() & 0xfff) as usize
};
occupied += HDR;
if m.skip_first {
occupied -= Self::current_size(m.page.as_page(), &m.c1) as usize;
}
if let Some((k, v)) = m.ins {
occupied += 8 + crate::alloc_size(k, v) as usize;
if let Some((k, v)) = m.ins2 {
occupied += 8 + crate::alloc_size(k, v) as usize;
}
}
occupied
}
}
fn replace<'a, T: AllocPage>(
txn: &mut T,
page: CowPage,
mutable: bool,
c: &Self::Cursor,
k0: &'a K,
v0: &'a V,
k1v1: Option<(&'a K, &'a V)>,
l: u64,
r: u64,
) -> Result<Put<'a, K, V>, T::Error> {
assert!(c.cur >= 0);
assert!(!c.is_leaf);
put::put::<_, _, _, Internal>(txn, page, mutable, true, c.cur as usize, k0, v0, k1v1, l, r)
fn size<K: Representable + ?Sized, V: Representable + ?Sized>(
m: &ModifiedPage<K, V, Page<K, V>>,
) -> usize {
let mut total = {
let hdr = header(m.page.as_page());
(hdr.left_page() & 0xfff) as usize
};
total += HDR;
let extra = if m.c1.is_leaf { 2 } else { 8 };
if let Some((k, v)) = m.ins {
total += extra + crate::alloc_size(k, v) as usize;
if let Some((k, v)) = m.ins2 {
total += extra + crate::alloc_size(k, v) as usize;
}
}
if m.skip_first {
total -= <Page<K, V> as BTreePage<K, V>>::current_size(m.page.as_page(), &m.c1) as usize;
}
total
}
unsafe fn unchecked_current_ptr(page: crate::Page, c: &Self::Cursor) -> *const u8 {
page.data.as_ptr().add(if c.is_leaf {
u16::from_le(*(page.data.as_ptr().add(HDR + c.cur as usize * 2) as *const u16)) as usize
} else {
(u64::from_le(*(page.data.as_ptr().add(HDR + c.cur as usize * 8) as *const u64))
& 0xfff) as usize
})
}
fn split_at(_: crate::Page, c: &Self::Cursor) -> (Self::Cursor, Self::Cursor) {
/// Split a cursor, returning two cursors `(a, b)` where b is the
/// same as `c`, and `a` is a cursor running from the first
/// element of the page to `c` (excluding `c`).
fn split_at(c: &Self::Cursor) -> (Self::Cursor, Self::Cursor) {
impl<K: Representable, V: Representable> super::BTreePage<K, V> for Page<K, V> {
fn is_dirty(page: crate::Page) -> bool {
header(page).is_dirty()
}
type Cursor = PageCursor;
fn is_empty(_: crate::Page, c: &Self::Cursor) -> bool {
c.cur >= c.total as isize
}
fn is_init(_: crate::Page, c: &Self::Cursor) -> bool {
c.cur < 0
}
fn cursor_before(p: crate::Page) -> Self::Cursor {
PageCursor::new(p, -1)
}
fn cursor_after(p: crate::Page) -> Self::Cursor {
PageCursor::after(p)
}
fn current<'a, T: LoadPage>(
txn: &T,
page: crate::Page<'a>,
c: &Self::Cursor,
) -> Option<(&'a K, &'a V, u64)> {
if c.cur < 0 || c.cur >= c.total as isize {
None
} else if c.is_leaf {
let f = tuple_size::<K, V>();
let off = {
let al = K::ALIGN.max(V::ALIGN);
let hdr = (HDR + al - 1) & !(al - 1);
hdr + c.cur as usize * f
};
unsafe {
let (k, v) = read::<T, K, V>(txn, page.data.as_ptr().add(off as usize));
Some((
K::from_raw_ptr(txn, k as *const u8),
V::from_raw_ptr(txn, v as *const u8),
0,
))
}
} else {
unsafe {
let off =
u64::from_le(*(page.data.as_ptr().add(HDR) as *const u64).add(c.cur as usize));
let (k, v) = read::<T, K, V>(txn, page.data.as_ptr().add((off & 0xfff) as usize));
Some((
K::from_raw_ptr(txn, k as *const u8),
V::from_raw_ptr(txn, v as *const u8),
off & !0xfff,
))
}
}
}
fn current_size(page: crate::Page, c: &Self::Cursor) -> usize {
assert!(c.cur >= 0 && c.cur < c.total as isize);
unsafe {
if c.is_leaf {
tuple_size::<K, V>()
} else {
8 + entry_size::<K, V>(page.data.as_ptr().add(
(u64::from_le(*(page.data.as_ptr().add(HDR) as *const u64).add(c.cur as usize))
& 0xfff) as usize,
))
}
}
}
fn move_next(c: &mut Self::Cursor) -> bool {
if c.cur < c.total as isize {
c.cur += 1;
true
} else {
false
}
}
fn move_prev(c: &mut Self::Cursor) -> bool {
if c.cur > 0 {
c.cur -= 1;
true
} else {
c.cur = -1;
false
}
}
fn left_child(page: crate::Page, c: &Self::Cursor) -> u64 {
assert!(c.cur >= 0);
if c.is_leaf {
0
} else {
let off =
unsafe { *(page.data.as_ptr().add((HDR + c.cur as usize * 8) - 8) as *const u64) };
u64::from_le(off) & !0xfff
}
}
fn right_child(page: crate::Page, c: &Self::Cursor) -> u64 {
assert!(c.cur < c.total as isize);
if c.is_leaf {
0
} else {
let off =
unsafe { *(page.data.as_ptr().offset(HDR as isize + c.cur * 8) as *const u64) };
u64::from_le(off) & !0xfff
}
}
fn set_cursor<'a, T: LoadPage>(
txn: &T,
page: crate::Page,
c: &mut PageCursor,
k0: &K,
v0: Option<&V>,
) -> Result<(&'a K, &'a V, u64), usize> {
unsafe {
let lookup = lookup(txn, page, c, k0, v0);
let result;
c.cur = match lookup {
Ok(n) => {
result = if c.is_leaf {
let f = tuple_size::<K, V>();
let off = {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
(0, (hdr_size + f * n) as u16)
};
Ok(Leaf::kv(txn, page, off))
} else {
let off =
u64::from_le(*(page.data.as_ptr().add(HDR + n * 8) as *const u64));
Ok(Internal::kv(
txn,
page,
(off & !0xfff, (off & 0xfff) as u16),
))
};
n as isize
}
Err(n) => {
result = Err(n);
n as isize
}
};
result
}
}
fn size(m: &ModifiedPage<K, V, Self>) -> usize {
let mut total = {
let hdr = header(m.page.as_page());
(hdr.left_page() & 0xfff) as usize
};
if m.c1.is_leaf {
let al = K::ALIGN.max(V::ALIGN);
total += (HDR + al - 1) & (!al - 1);
} else {
total += HDR
};
if let Some((k, v)) = m.ins {
let extra = if m.c1.is_leaf { 8 } else { 0 };
total += extra + crate::alloc_size(k, v) as usize;
if let Some((k, v)) = m.ins2 {
total += extra + crate::alloc_size(k, v) as usize;
}
}
if m.skip_first {
total -= Self::current_size(m.page.as_page(), &m.c1) as usize;
}
total
}
fn replace<'a, T: AllocPage>(
txn: &mut T,
page: CowPage,
mutable: bool,
c: &Self::Cursor,
k0: &'a K,
v0: &'a V,
k1v1: Option<(&'a K, &'a V)>,
l: u64,
r: u64,
) -> Result<Put<'a, K, V>, T::Error> {
if r == 0 {
put::put::<_, _, _, Leaf>(txn, page, mutable, true, c.cur as usize, k0, v0, k1v1, 0, 0)
} else {
put::put::<_, _, _, Internal>(
txn,
page,
mutable,
true,
c.cur as usize,
k0,
v0,
k1v1,
l,
r,
)
}
}
unsafe {
if m.modified.c0.is_leaf {
merge::<_, _, _, Leaf>(txn, &mut new, m)
} else {
merge::<_, _, _, Internal>(txn, &mut new, m)
}
if m.modified.c0.is_leaf {
merge::<_, _, _, Leaf>(txn, &mut new, m)
} else {
merge::<_, _, _, Internal>(txn, &mut new, m)
impl<K: Representable, V: Representable> super::BTreePage<K, V> for Page<K, V> {
fn is_dirty(page: crate::Page) -> bool {
header(page).is_dirty()
}
fn is_empty(_: crate::Page, c: &Self::Cursor) -> bool {
c.cur >= c.total as isize
}
fn is_init(_: crate::Page, c: &Self::Cursor) -> bool {
c.cur < 0
}
type Cursor = PageCursor;
fn cursor_before(p: crate::Page) -> Self::Cursor {
PageCursor::new(p, -1)
}
fn cursor_after(p: crate::Page) -> Self::Cursor {
PageCursor::after(p)
}
fn current<'a, T: LoadPage>(
txn: &T,
page: crate::Page<'a>,
c: &Self::Cursor,
) -> Option<(&'a K, &'a V, u64)> {
if c.cur < 0 || c.cur >= c.total as isize {
None
} else if c.is_leaf {
let f = tuple_size::<K, V>();
let off = {
let al = K::ALIGN.max(V::ALIGN);
let hdr = (HDR + al - 1) & !(al - 1);
hdr + c.cur as usize * f
};
unsafe {
let (k, v) = read::<T, K, V>(txn, page.data.as_ptr().add(off as usize));
Some((
K::from_raw_ptr(txn, k as *const u8),
V::from_raw_ptr(txn, v as *const u8),
0,
))
}
} else {
unsafe {
let off =
u64::from_le(*(page.data.as_ptr().add(HDR) as *const u64).add(c.cur as usize));
let (k, v) = read::<T, K, V>(txn, page.data.as_ptr().add((off & 0xfff) as usize));
Some((
K::from_raw_ptr(txn, k as *const u8),
V::from_raw_ptr(txn, v as *const u8),
off & !0xfff,
))
}
fn size<K: Representable, V: Representable>(m: &ModifiedPage<K, V, Page<K, V>>) -> usize {
let mut total = {
let hdr = header(m.page.as_page());
(hdr.left_page() & 0xfff) as usize
};
if m.c1.is_leaf {
let al = K::ALIGN.max(V::ALIGN);
total += (HDR + al - 1) & (!al - 1);
} else {
total += HDR
};
if let Some((k, v)) = m.ins {
let extra = if m.c1.is_leaf { 0 } else { 8 };
total += extra + crate::alloc_size(k, v) as usize;
if let Some((k, v)) = m.ins2 {
total += extra + crate::alloc_size(k, v) as usize;
unsafe fn unchecked_current_ptr(page: crate::Page, c: &Self::Cursor) -> *const u8 {
assert!(c.cur >= 0 && c.cur < c.total as isize);
page.data.as_ptr().add(if c.is_leaf {
let f = tuple_size::<K, V>();
let al = K::ALIGN.max(V::ALIGN);
let hdr = (HDR + al - 1) & !(al - 1);
hdr + c.cur as usize * f
} else {
(u64::from_le(*(page.data.as_ptr().add(HDR + c.cur as usize * 8) as *const u64))
& 0xfff) as usize
})
}
fn current_size(page: crate::Page, c: &Self::Cursor) -> usize {
assert!(c.cur >= 0 && c.cur < c.total as isize);
unsafe {
if c.is_leaf {
tuple_size::<K, V>()
} else {
8 + entry_size::<K, V>(page.data.as_ptr().add(
(u64::from_le(*(page.data.as_ptr().add(HDR) as *const u64).add(c.cur as usize))
& 0xfff) as usize,
))
}
}
}
fn move_next(_page: crate::Page, c: &mut Self::Cursor) -> bool {
if c.cur < c.total as isize {
c.cur += 1;
true
} else {
false
}
}
fn move_prev(_page: crate::Page, c: &mut Self::Cursor) -> bool {
if c.cur > 0 {
c.cur -= 1;
true
} else {
c.cur = -1;
false
}
}
fn left_child(page: crate::Page, c: &Self::Cursor) -> u64 {
assert!(c.cur >= 0);
if c.is_leaf {
0
} else {
let off =
unsafe { *(page.data.as_ptr().add((HDR + c.cur as usize * 8) - 8) as *const u64) };
u64::from_le(off) & !0xfff
}
}
fn right_child(page: crate::Page, c: &Self::Cursor) -> u64 {
assert!(c.cur < c.total as isize);
if c.is_leaf {
0
} else {
let off =
unsafe { *(page.data.as_ptr().offset(HDR as isize + c.cur * 8) as *const u64) };
u64::from_le(off) & !0xfff
}
}
fn set_cursor<'a, T: LoadPage>(
txn: &T,
page: crate::Page,
c: &mut PageCursor,
k0: &K,
v0: Option<&V>,
) -> Result<(&'a K, &'a V, u64), usize> {
unsafe {
let lookup = lookup(txn, page, c, k0, v0);
let result;
c.cur = match lookup {
Ok(n) => {
result = if c.is_leaf {
let f = tuple_size::<K, V>();
let off = {
let al = K::ALIGN.max(V::ALIGN);
let hdr_size = (HDR + al - 1) & !(al - 1);
(0, (hdr_size + f * n) as u16)
};
Ok(Leaf::kv(txn, page, off))
} else {
let off =
u64::from_le(*(page.data.as_ptr().add(HDR + n * 8) as *const u64));
Ok(Internal::kv(
txn,
page,
(off & !0xfff, (off & 0xfff) as u16),
))
};
n as isize
}
Err(n) => {
result = Err(n);
n as isize
}
};
result
}
}
fn split_at(_: crate::Page, c: &Self::Cursor) -> (Self::Cursor, Self::Cursor) {
(
PageCursor {
cur: 0,
total: c.cur.max(0) as usize,
is_leaf: c.is_leaf,
},
*c,
)
if m.skip_first {
total -= <Page<K, V> as BTreePage<K, V>>::current_size(m.page.as_page(), &m.c1) as usize;
if let Put::Ok(Ok { page, freed }) =
<Page<K, V>>::put(txn, new_left.0, true, &lc, m.mid.0, m.mid.1, None, 0, rl)?
{
if let Put::Ok(Ok { page, freed }) = <Page<K, V>>::put(
txn, new_left.0, true, false, &lc, m.mid.0, m.mid.1, None, 0, rl,
)? {
fn move_next(p: Page, c: &mut Self::Cursor) -> bool;
fn move_prev(p: Page, c: &mut Self::Cursor) -> bool;
/// Move the cursor to the next position. Returns whether the
/// cursor was actually moved (i.e. `true` if and only if the
/// cursor isn't at the end of the page already).
fn move_next(c: &mut Self::Cursor) -> bool;
/// Move the cursor to the previous position. Returns whether the
/// cursor was actually moved (i.e. `true` if and only if the
/// cursor isn't strictly before the page).
fn move_prev(c: &mut Self::Cursor) -> bool;
/// Returns the current element, if the cursor is pointing at one.
fn split_at(p: Page, c: &Self::Cursor) -> (Self::Cursor, Self::Cursor);
fn is_empty(p: Page, c: &Self::Cursor) -> bool;
fn is_init(p: Page, c: &Self::Cursor) -> bool;
fn split_at(c: &Self::Cursor) -> (Self::Cursor, Self::Cursor);
fn replace<'a, T: AllocPage>(
txn: &mut T,
page: CowPage,
mutable: bool,
c: &Self::Cursor,
k0: &'a K,
v0: &'a V,
k1v1: Option<(&'a K, &'a V)>,
l: u64,
r: u64,
) -> Result<Put<'a, K, V>, T::Error>;
/// Merge, rebalance or update a concatenation.
fn modify<'a, T: AllocPage>(
txn: &mut T,
m: &mut ModifiedPage<'a, K, V, Self>,
) -> Result<Put<'a, K, V>, T::Error> {
debug!("modify: {:?}", m);
if let Some((k, v)) = m.ins {
if m.skip_first {
Self::replace(txn, m.page, m.mutable, &m.c1, k, v, m.ins2, m.l, m.r)
} else {
Self::put(txn, m.page, m.mutable, &m.c1, k, v, m.ins2, m.l, m.r)
}
} else {
if m.skip_first {
let (page, freed) = Self::del(txn, m.page, m.mutable, &m.c1, m.l)?;
Ok(Put::Ok(Ok { freed, page }))
} else if m.l > 0 {
Ok(Put::Ok(Self::update_left_child(
txn, m.page, m.mutable, &m.c1, m.l,
)?))
} else {
let mut c1 = m.c1.clone();
Self::move_next(m.page.as_page(), &mut c1);
Ok(Put::Ok(Self::update_left_child(
txn, m.page, m.mutable, &c1, m.r,
)?))
}
}
}
fn size(m: &ModifiedPage<K, V, Self>) -> usize;
/// Apply the modifications to a page.
fn modify<
'a,
T: AllocPage,
K: Representable + ?Sized,
V: Representable + ?Sized,
P: BTreeMutPage<K, V>,
>(
txn: &mut T,
m: &mut ModifiedPage<'a, K, V, P>,
) -> Result<Put<'a, K, V>, T::Error> {
debug!("modify: {:?}", m);
if let Some((k, v)) = m.ins {
P::put(
txn,
m.page,
m.mutable,
m.skip_first,
&m.c1,
k,
v,
m.ins2,
m.l,
m.r,
)
} else {
if m.skip_first {
let (page, freed) = P::del(txn, m.page, m.mutable, &m.c1, m.l)?;
Ok(Put::Ok(Ok { freed, page }))
} else if m.l > 0 {
Ok(Put::Ok(P::update_left_child(
txn, m.page, m.mutable, &m.c1, m.l,
)?))
} else {
let mut c1 = m.c1.clone();
P::move_next(&mut c1);
Ok(Put::Ok(P::update_left_child(
txn, m.page, m.mutable, &c1, m.r,
)?))
}
}
}