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}