bbolt_rs/
util.rs

1use crate::common::page::meta::{MappedMetaPage, MetaPage};
2use crate::common::page::{CoerciblePage, MutPage};
3use crate::common::SplitRef;
4use crate::iter::{DbWalker, ValueBucketSeq};
5use crate::tx::{TxCell, TxIApi};
6use crate::{Bolt, BucketRwApi, DbApi, DbPath, PgId, TxRwApi, TxRwRefApi};
7use aligners::{alignment, AlignedBytes};
8use std::fs::OpenOptions;
9use std::ops::Deref;
10use std::path::Path;
11
12#[cfg(test)]
13fn copy<P: AsRef<Path>>(cell: TxCell, path: P) {
14  let mut f = OpenOptions::new()
15    .write(true)
16    .truncate(true)
17    .open(path)
18    .unwrap();
19  let page_size = cell.page_size();
20  let meta = *cell.meta();
21  let db_path = cell.split_r().db;
22  let mut bytes = AlignedBytes::<alignment::Page>::new_zeroed(page_size);
23  {
24    let mut page = MutPage::new(bytes.as_mut_ptr());
25    let meta_page = MappedMetaPage::mut_into(&mut page);
26    meta_page.page.set_meta();
27    meta_page.meta = meta;
28
29    meta_page.page.id = PgId(0);
30    let checksum = meta_page.meta.checksum();
31    meta_page.meta.set_checksum(checksum);
32  }
33  {
34    let mut page = MutPage::new(bytes.as_mut_ptr());
35    let meta_page = MappedMetaPage::coerce_mut(&mut page).unwrap();
36
37    meta_page.page.id = PgId(1);
38    let txid = meta_page.meta.txid();
39    meta_page.meta.set_txid(txid - 1);
40    let checksum = meta_page.meta.checksum();
41    meta_page.meta.set_checksum(checksum);
42  }
43}
44
45pub fn compact(src: &Bolt, dst: &mut Bolt, tx_max_size: u64) -> crate::Result<()> {
46  if dst.path() != &DbPath::Memory {
47    assert_ne!(src.path(), dst.path());
48  }
49  let mut size = 0u64;
50  let mut dst_tx = dst.begin_rw_tx()?;
51
52  let src_tx = src.begin_tx()?;
53  let mut walker = DbWalker::new(src_tx.tx.api_cursor());
54  while let Some((k, v)) = walker.next() {
55    let sz = (k.len() + v.len()) as u64;
56    if size + sz > tx_max_size && tx_max_size != 0 {
57      dst_tx.commit()?;
58      dst_tx = dst.begin_rw_tx()?;
59      size = 0;
60    }
61    size += sz;
62    let path = walker.path();
63    let mut b = dst_tx.bucket_mut_path(path).unwrap();
64    b.set_fill_percent(1.0);
65    match v {
66      ValueBucketSeq::Value(v) => {
67        b.put(k, v)?;
68      }
69      ValueBucketSeq::BucketSeq(seq) => {
70        let mut b = b.create_bucket(k)?;
71        b.set_sequence(seq)?;
72      }
73    }
74  }
75  Ok(())
76}