1use crate::CACHE_LINE_SIZE;
2use crate::bptree::{
3 self, BTree, entry::*, helper::PathBuffer, inter::*, leaf::*, node::*, tree::BTreeInner, *,
4};
5use alloc::alloc::{Layout, alloc, dealloc, handle_alloc_error, realloc};
6use core::fmt::{self, Debug};
7use core::mem::{align_of, size_of};
8use core::num::NonZeroUsize;
9
10pub type BTreeMap<K, V> = bptree::BTree<K, V, TreeInfo>;
11pub use bptree::cursor::Cursor;
12pub use bptree::iter::{Iter, IterMut, Keys, Range, RangeMut, Values, ValuesMut};
13pub type IntoIter<K, V> = bptree::iter::IntoIter<K, V, TreeInfo>;
14pub type Entry<'a, K, V> = bptree::entry::Entry<'a, K, V, TreeInfo>;
15pub type OccupiedEntry<'a, K, V> = bptree::entry::OccupiedEntry<'a, K, V, TreeInfo>;
16pub type VacantEntry<'a, K, V> = bptree::entry::VacantEntry<'a, K, V, TreeInfo>;
17
18pub struct TreeInfo(NonZeroUsize);
40
41const EMPTY_FLAG: usize = 1;
42
43unsafe impl Send for TreeInfo {}
44unsafe impl Sync for TreeInfo {}
45
46impl Default for TreeInfo {
47 #[inline]
48 fn default() -> Self {
49 Self(unsafe { NonZeroUsize::new_unchecked(EMPTY_FLAG) })
50 }
51}
52
53impl Debug for TreeInfo {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 write!(f, "TreeInfo")
57 }
58}
59
60#[repr(C)]
64struct TreeInfoHeader {
65 leaf_count: usize,
66 inter_count: u32,
67 cap: u8,
69 entry_idx: u8,
70 len: u8,
73 buffer_pos: i8,
75}
76
77impl TreeInfoHeader {
78 #[inline]
79 fn clear(&mut self) {
80 self.entry_idx = 0;
81 self.len = 0;
82 self.buffer_pos = 0;
83 }
84}
85
86impl Stats for TreeInfo {}
87
88impl StatsPriv for TreeInfo {
89 type EntryInner<'a, K, V>
90 = TreeInfoEntry<'a, K, V>
91 where
92 K: Key + 'a,
93 V: Value + 'a;
94
95 type PathBufferRef<'a> = &'a mut Self;
96
97 type PathBuffer = Self;
98
99 type BufferStack = ();
100
101 #[inline]
102 fn get_cache<'a, K>(&'a mut self, _stack: &mut (), root: Option<InterNode<K>>) -> &'a mut Self {
103 if let Some(root) = root.as_ref() {
104 self.ensure_cap(root.height());
105 } else {
106 self.clear_cache();
107 }
108 self
109 }
110
111 #[inline]
112 fn take_cache<K>(mut self, _root: Option<InterNode<K>>) -> Self {
113 self.clear_cache();
115 self
116 }
117
118 #[cfg(test)]
119 fn init_count(&mut self, leaf_count: usize, inter_count: u32) {
120 if let Some(header) = self.header_mut() {
121 header.leaf_count = leaf_count;
122 header.inter_count = inter_count;
123 } else {
124 self._alloc(leaf_count, inter_count, 0);
125 }
126 }
127
128 #[inline]
129 fn search_entry<'a, K: Key, V: Value>(
130 tree: &'a mut BTree<K, V, Self>, key: K,
131 ) -> Entry<'a, K, V> {
132 if let Some(root) = tree.inner.get_root() {
133 let mut is_seq = true;
134 let leaf = match root {
135 Node::Inter(inter) => {
136 let mut stack = ();
137 let mut cache = tree.stats.get_cache(&mut stack, Some(inter.clone()));
138 inter.find_leaf_with_cache_smart::<K, V, _>(&mut cache, &key, &mut is_seq)
139 }
140 Node::Leaf(leaf) => {
141 tree.stats.clear_cache();
142 leaf
143 }
144 };
145 let (idx, is_equal) = leaf.search_smart(&key, is_seq);
146 let mut inner = TreeInfoEntry { tree };
147 inner.set_idx(idx);
148 if is_equal {
149 Entry::Occupied(OccupiedEntry { inner, leaf })
150 } else {
151 Entry::Vacant(VacantEntry { inner, key, leaf: Some(leaf) })
152 }
153 } else {
154 let inner = TreeInfoEntry { tree };
155 Entry::Vacant(VacantEntry { inner, key, leaf: None })
157 }
158 }
159
160 #[inline]
162 fn seek_entry<'a, K: Key, V: Value, const FIRST: bool>(
163 tree: &'a mut BTree<K, V, Self>,
164 ) -> Option<OccupiedEntry<'a, K, V>> {
165 if let Some(root) = tree.inner.get_root() {
166 let leaf = match root {
167 Node::Inter(inter) => {
168 let mut stack = ();
169 let mut cache = tree.stats.get_cache(&mut stack, Some(inter.clone()));
170 if FIRST {
171 inter.find_first_leaf_with_cache::<V, _>(&mut cache)
172 } else {
173 inter.find_last_leaf_with_cache::<V, _>(&mut cache)
174 }
175 }
176 Node::Leaf(leaf) => {
177 tree.stats.clear_cache();
179 leaf
180 }
181 };
182 let count = leaf.key_count();
183 if count > 0 {
184 let mut inner = TreeInfoEntry { tree };
185 if FIRST {
186 inner.set_idx(0);
187 } else {
188 inner.set_idx(count - 1);
189 };
190 return Some(OccupiedEntry { inner, leaf });
191 }
192 }
193 None
194 }
195
196 #[cfg(test)]
197 fn assert_leaf_count(&self, leaf_count: usize) {
198 assert_eq!(self.leaf_count(), leaf_count);
199 }
200
201 #[cfg(test)]
202 fn assert_inter_count(&self, inter_count: usize) {
203 assert_eq!(self.inter_count() as usize, inter_count);
204 }
205}
206
207pub(crate) struct TreeInfoEntry<'a, K, V>
208where
209 K: Key,
210 V: Value,
211{
212 tree: &'a mut BTree<K, V, TreeInfo>,
213}
214
215impl<'a, K: Key, V: Value> EntryInner<K, V> for TreeInfoEntry<'a, K, V> {
216 #[inline(always)]
217 fn get_cache(&mut self) -> impl PathBuffer {
218 &mut self.tree.stats
219 }
220
221 #[cfg(test)]
222 #[inline(always)]
223 fn get_tree(&self) -> &BTreeInner<K, V> {
224 &self.tree.inner
225 }
226
227 #[inline(always)]
228 fn get_tree_cache(&mut self) -> (&mut BTreeInner<K, V>, impl PathBuffer) {
229 let (tree, stats) = (&mut self.tree.inner, &mut self.tree.stats);
230 (tree, stats)
231 }
232
233 #[inline(always)]
234 fn set_idx(&mut self, idx: u8) {
235 self.tree.stats.set_entry_idx(idx);
236 }
237
238 #[inline(always)]
239 fn get_idx(&self) -> u8 {
240 self.tree.stats.get_entry_idx()
241 }
242}
243
244impl TreeInfo {
245 const ITEM_SIZE: usize = size_of::<(*mut u8, u8)>();
246
247 const ITEMS_OFFSET: usize = {
249 let hs = size_of::<TreeInfoHeader>();
250 let ia = align_of::<(*mut u8, u8)>();
251 let offset = (hs + ia - 1) & !(ia - 1);
252 if offset != hs {
253 panic!("TreeInfoHeader is not aligned");
254 }
255 offset
256 };
257
258 #[inline]
260 fn clear_cache(&mut self) {
261 if self.0.get() & EMPTY_FLAG == 0 {
262 let header = self.header_mut_unwrap();
263 header.len = 0;
264 header.buffer_pos = 0;
265 header.entry_idx = 0;
266 } else {
267 *self = Self::default();
268 }
269 }
270
271 #[inline]
272 fn set_entry_idx(&mut self, entry_idx: u8) {
273 if self.0.get() & EMPTY_FLAG == 0 {
274 self.header_mut_unwrap().entry_idx = entry_idx;
275 } else {
276 self.0 = unsafe { NonZeroUsize::new_unchecked((entry_idx as usize) << 8 | EMPTY_FLAG) };
277 }
278 }
279
280 #[inline]
282 fn ensure_cap(&mut self, height: u8) {
283 assert!(height < u8::MAX);
284 match self.header_mut_or() {
285 Ok(header) => {
286 if height <= header.cap {
287 header.clear();
288 } else {
289 let old_cap = header.cap;
290 let old_size = Self::buf_size_from_cap(old_cap);
292 let new_size = old_size + CACHE_LINE_SIZE;
294 let new_cap = Self::cal_cap(new_size);
295 let old_layout = Self::get_layout(old_size);
296 unsafe {
297 let p = realloc(self.0.get() as *mut u8, old_layout, new_size);
298 if !p.is_null() {
299 crate::trace_log!("grow pathbuf cap {old_cap}->{new_cap}");
300 let header = p as *mut TreeInfoHeader;
301 (*header).cap = new_cap;
302 (*header).clear();
303 self.0 = NonZeroUsize::new_unchecked(p as usize);
304 } else {
305 handle_alloc_error(Self::get_layout(new_size));
306 }
307 }
308 }
309 }
310 Err(entry_idx) => {
311 if height > 0 {
312 self._alloc(2, 1, entry_idx);
314 }
315 }
316 }
317 }
318
319 #[inline]
320 fn leaf_count(&self) -> usize {
321 if let Some(header) = self.header() { header.leaf_count } else { 1 }
322 }
323
324 #[inline(always)]
325 fn inter_count(&self) -> u32 {
326 if let Some(header) = self.header() { header.inter_count } else { 0 }
327 }
328
329 #[inline(always)]
330 const fn cal_cap(buf_size: usize) -> u8 {
331 ((buf_size - Self::ITEMS_OFFSET) / Self::ITEM_SIZE) as u8
332 }
333
334 #[inline(always)]
335 const fn buf_size_from_cap(cap: u8) -> usize {
336 let size = cap as usize * Self::ITEM_SIZE + Self::ITEMS_OFFSET;
337 #[cfg(debug_assertions)]
338 {
339 if !size.is_multiple_of(CACHE_LINE_SIZE) {
340 panic!("not aligned");
341 }
342 }
343 size
344 }
345
346 #[inline(always)]
347 const fn get_layout(buf_size: usize) -> Layout {
348 let align = align_of::<usize>();
349 #[cfg(debug_assertions)]
350 {
351 if align_of::<(*mut u8, u8)>() != align {
352 panic!("TreeInfoHeader is not aligned");
353 }
354 }
355 unsafe { Layout::from_size_align_unchecked(buf_size, align) }
356 }
357
358 #[inline]
359 fn _alloc(&mut self, leaf_count: usize, inter_count: u32, entry_idx: u8) {
360 debug_assert!(self.header().is_none());
361 unsafe {
362 let layout = Self::get_layout(CACHE_LINE_SIZE);
363 let cap = Self::cal_cap(CACHE_LINE_SIZE);
364 let p = alloc(layout);
365 if !p.is_null() {
366 crate::trace_log!("alloc pathbuf cap {cap}");
367 let header = p as *mut TreeInfoHeader;
368 header.write(TreeInfoHeader {
369 leaf_count,
370 inter_count,
371 entry_idx,
372 cap,
373 len: 0,
374 buffer_pos: 0,
375 });
376 self.0 = NonZeroUsize::new_unchecked(p as usize);
377 } else {
378 handle_alloc_error(layout);
379 }
380 }
381 }
382
383 #[inline]
384 fn header(&self) -> Option<&TreeInfoHeader> {
385 let this = self.0.get();
386 if this & EMPTY_FLAG == 0 {
387 let p = this as *mut TreeInfoHeader;
388 Some(unsafe { &*p })
389 } else {
390 None
391 }
392 }
393
394 #[inline]
395 fn get_entry_idx(&self) -> u8 {
396 let this = self.0.get();
397 if this & EMPTY_FLAG == 0 {
398 let p = this as *mut TreeInfoHeader;
399 unsafe { (*p).entry_idx }
400 } else {
401 (self.0.get() >> 8) as u8
402 }
403 }
404
405 #[inline]
406 fn header_mut(&mut self) -> Option<&mut TreeInfoHeader> {
407 let this = self.0.get();
408 if this & EMPTY_FLAG == 0 {
409 let p = this as *mut TreeInfoHeader;
410 Some(unsafe { &mut *p })
411 } else {
412 None
413 }
414 }
415
416 #[inline]
417 fn header_mut_or(&mut self) -> Result<&mut TreeInfoHeader, u8> {
418 let this = self.0.get();
419 if this & EMPTY_FLAG == 0 {
420 let p = this as *mut TreeInfoHeader;
421 Ok(unsafe { &mut *p })
422 } else {
423 Err((self.0.get() >> 8) as u8)
424 }
425 }
426
427 #[inline]
428 fn header_ptr_unwrap(&mut self) -> *mut TreeInfoHeader {
429 let this = self.0.get();
430 debug_assert_eq!(this & EMPTY_FLAG, 0);
431 this as *mut TreeInfoHeader
432 }
433
434 #[inline]
435 fn header_mut_unwrap(&mut self) -> &mut TreeInfoHeader {
436 unsafe { &mut *self.header_ptr_unwrap() }
437 }
438
439 #[inline]
440 unsafe fn item_ptr(&self, idx: u8) -> *mut (NodeBase, u8) {
441 debug_assert_eq!(self.0.get() & EMPTY_FLAG, 0);
442 unsafe {
443 (self.0.get() as *mut u8).add(Self::ITEMS_OFFSET + idx as usize * Self::ITEM_SIZE)
444 as *mut _
445 }
446 }
447}
448
449impl Drop for TreeInfo {
450 #[inline]
451 fn drop(&mut self) {
452 if self.0.get() & EMPTY_FLAG == 0 {
453 let p = self.0.get() as *mut TreeInfoHeader;
454 unsafe {
455 let size = Self::buf_size_from_cap((*p).cap);
456 dealloc(p as *mut u8, Self::get_layout(size));
457 }
458 }
459 }
460}
461
462impl PathBuffer for TreeInfo {
463 #[inline(always)]
466 fn inc_leaf_count(&mut self) {
467 match self.header_mut_or() {
468 Ok(header) => {
469 header.leaf_count += 1;
470 crate::trace_log!("inc_leaf_count {}", header.leaf_count);
471 }
472 Err(entry_idx) => {
473 self._alloc(2, 1, entry_idx);
474 }
475 }
476 }
477
478 #[inline(always)]
479 fn dec_leaf_count(&mut self) {
480 self.header_mut_unwrap().leaf_count -= 1;
481 }
482
483 #[inline(always)]
488 fn inc_inter_count(&mut self) {
489 match self.header_mut() {
490 Some(header) => {
491 header.inter_count += 1;
492 crate::trace_log!("inc inter_count {}", header.inter_count);
493 }
494 None => unreachable!(),
495 }
496 }
497
498 #[inline(always)]
499 fn dec_inter_count(&mut self) {
500 self.header_mut_unwrap().inter_count -= 1;
501 crate::trace_log!("dec inter_count {}", self.header_mut_unwrap().inter_count);
502 }
503
504 fn buffer_len(&self) -> u8 {
508 if let Some(header) = self.header() { header.len } else { 0 }
509 }
510
511 #[inline]
514 fn buffer_pos(&self) -> i8 {
515 if let Some(header) = self.header() { header.buffer_pos } else { 0 }
516 }
517
518 #[inline]
519 fn _set_pos(&mut self, buffer_pos: i8) {
520 if let Some(header) = self.header_mut() {
521 header.buffer_pos = buffer_pos;
522 }
523 }
524
525 #[inline]
527 fn _push(&mut self, inter: NodeBase, idx: u8) {
528 let header = self.header_mut_unwrap();
529 let wi = header.len;
530 header.len = wi + 1;
531 debug_assert!(wi < header.cap, "{wi} {}", header.cap);
532 unsafe { self.item_ptr(wi).write((inter, idx)) };
533 }
534
535 #[inline]
536 unsafe fn _get_unchecked(&self, idx: u8) -> (NodeBase, u8) {
537 unsafe {
538 let p = &*self.item_ptr(idx);
539 (p.0.clone(), p.1)
540 }
541 }
542
543 #[inline]
545 fn _pop(&mut self) -> Option<(NodeBase, u8)> {
546 let header = self.header_mut()?;
547 let mut wi = header.len;
548 if wi > 0 {
549 wi -= 1;
550 header.len = wi;
551 unsafe { Some(self.item_ptr(wi).read()) }
552 } else {
553 None
554 }
555 }
556
557 #[inline]
558 fn _last(&self) -> Option<(NodeBase, u8)> {
559 let header = self.header()?;
560 let mut wi = header.len;
561 if wi > 0 {
562 wi -= 1;
563 unsafe { Some(self.item_ptr(wi).read()) }
564 } else {
565 None
566 }
567 }
568}
569
570impl PathBuffer for &mut TreeInfo {
571 #[inline]
575 fn inc_leaf_count(&mut self) {
576 PathBuffer::inc_leaf_count(*self)
577 }
578
579 #[inline]
580 fn dec_leaf_count(&mut self) {
581 PathBuffer::dec_leaf_count(*self)
582 }
583
584 #[inline]
585 fn inc_inter_count(&mut self) {
586 PathBuffer::inc_inter_count(*self)
587 }
588
589 #[inline]
590 fn dec_inter_count(&mut self) {
591 PathBuffer::dec_inter_count(*self)
592 }
593
594 #[inline]
598 fn buffer_len(&self) -> u8 {
599 PathBuffer::buffer_len(*self)
600 }
601
602 #[inline]
603 fn buffer_pos(&self) -> i8 {
604 PathBuffer::buffer_pos(*self)
605 }
606
607 #[inline]
608 fn _set_pos(&mut self, buffer_pos: i8) {
609 PathBuffer::_set_pos(*self, buffer_pos);
610 }
611
612 #[inline]
614 fn _push(&mut self, inter: NodeBase, idx: u8) {
615 PathBuffer::_push(*self, inter, idx)
616 }
617
618 #[inline]
620 fn _pop(&mut self) -> Option<(NodeBase, u8)> {
621 PathBuffer::_pop(*self)
622 }
623
624 #[inline]
625 unsafe fn _get_unchecked(&self, idx: u8) -> (NodeBase, u8) {
626 unsafe { PathBuffer::_get_unchecked(*self, idx) }
627 }
628
629 #[inline]
631 fn _last(&self) -> Option<(NodeBase, u8)> {
632 PathBuffer::_last(*self)
633 }
634}
635
636impl<K: Key, V: Value> BTree<K, V, TreeInfo> {
637 #[inline(always)]
639 pub fn leaf_count(&self) -> usize {
640 if self.inner.root.is_some() { self.stats.leaf_count() } else { 0 }
641 }
642
643 #[inline(always)]
645 pub fn inter_count(&self) -> usize {
646 self.stats.inter_count() as usize
647 }
648
649 #[inline]
650 pub fn memory_used(&self) -> usize {
651 (self.leaf_count() + self.inter_count()) * NODE_SIZE
652 }
653
654 #[inline]
658 pub fn get_fill_ratio(&self) -> f32 {
659 if self.inner.len == 0 {
660 0.0
661 } else {
662 let cap = LeafNode::<K, V>::cap() as usize * self.leaf_count();
663 self.inner.len as f32 / cap as f32 * 100.0
664 }
665 }
666}
667
668#[cfg(test)]
669mod tests {
670
671 use super::*;
672 use crate::bptree::tests::*;
673 use captains_log::logfn;
674 use rstest::*;
675 use std::vec::Vec;
676
677 #[logfn]
678 #[rstest]
679 fn test_tree_info_path_buffer(setup_log: ()) {
680 fn test_push_pop(info: &mut TreeInfo, height: u8) {
681 let mut nodes: Vec<InterNode<u32>> = Vec::new();
682 let root = unsafe { InterNode::<u32>::alloc(height) };
683 let mut _temp = ();
684 let cache = info.get_cache(&mut _temp, Some(root.clone()));
685 cache.push_path(root.clone(), height);
686 nodes.push(root);
687 for i in 1..height {
688 let node = unsafe { InterNode::<u32>::alloc(height - i) };
689 cache.push_path(node.clone(), height - i);
690 nodes.push(node);
691 }
692 let mut _nodes = Vec::new();
693 let mut i = 0;
694 while let Some((node, idx)) = cache.pop_path() {
695 i += 1;
696 assert_eq!(idx, i);
697 _nodes.insert(0, node);
698 }
699 assert_eq!(i, height);
700 assert_eq!(nodes, _nodes);
701 for node in nodes {
702 node.dealloc::<false>();
703 }
704 }
705 {
706 let mut info = TreeInfo::default();
707 assert!(info.header().is_none());
708 let inner0 = info.0.get();
709 assert_eq!(inner0 & EMPTY_FLAG, EMPTY_FLAG);
710 info.ensure_cap(3);
711 let inner1 = info.0.get();
712 assert_eq!(inner1 & EMPTY_FLAG, 0);
713 assert_eq!(info.header().unwrap().cap, 3);
714 info.ensure_cap(3);
715 assert_eq!(info.0.get(), inner1); test_push_pop(&mut info, 3);
717
718 assert_eq!(info.header().unwrap().cap, 3);
719 info.ensure_cap(7);
720 assert!(info.0.get() != inner1); assert_eq!(info.header().unwrap().cap, 7);
722
723 test_push_pop(&mut info, 7);
724 }
725 }
726}