W2MIZD5BNL7A5HVFWTESF57QU7T6QMEF4RBSLFQXMEEU3XD2NU2QC
OHUZ73MKWD7SSB4DKKA532DEQKXQDS6PZ6HJ3EC2DLVJSLQH3NLAC
HN6Z5DU4WYMAIOOSNVHLIIMNF6Q53TNJ7YC27SLKWNXVYCTACQKQC
G4JEQLLX6Q7VVFVAEJZAVQXX33MQ36CSCYSMJ5NQM5VZ76DXKU6QC
OP6SVMOD2GTQ7VNJ4E5KYFG4MIYA7HBMXJTADALMZH4PY7OQRMZQC
WS4ZQM4RMIHZ6XZKSDQJGHN5SSSWFL4H236USOPUA33S6RC53RFAC
XEU2QVLCHPYOOD4TQIPEEVYOVSFMKFPLJYWEJYXYJAZ7S54KWDZAC
OTWDDJE7TTE73D6BGF4ZN6BH2NFUFLPME2VJ3CPALH463UGWLEIQC
UAQX27N4PI4LHEW6LSHJETIE5MV7JTEMPLTJFYUBMYVPC43H7VOAC
OFINGD26ZWCRDVVDI2ZIBLMHXKEMJA6MRNLANJYUHQPIJLPA7J2AC
6DCQHIFPEH4GZKSRRS32GMKDRPZH4MTCGOUEI7YEUVKWENBF3JWAC
SO25TWFLSRQIVTJTTSN77LO5FZQVQPIZTSBULH7MWBBDEWSK3OCAC
EAAYH6BQWDK52EC5RG3BEZQU3FJPN5RRRN4U5KDKDVPKXBVJMNDAC
ONES3V466GLO5CXKRF5ENK7VFOQPWM3YXLVRGWB56V5SH3W7XNBQC
YXKP4AIWDBIWBBUDWF66YIPG5ECMHNKEV3PX6KYXOVXY3EWG3WGQC
YWFYZNLZ5JHLIFVBRKZK4TSWVPROUPRG77ZB5M7UHT2OKPL4ZSRQC
}
}
#[cfg(feature = "crc32")]
pub fn crc(&self, hasher: &crc32fast::Hasher) -> u32 {
let mut hasher = hasher.clone();
hasher.reset();
// Hash the beginning and the end of the page (i.e. remove
// the CRC).
unsafe {
hasher.update(core::slice::from_raw_parts(self.data, 4));
hasher.update(core::slice::from_raw_parts(
self.data.offset(8),
PAGE_SIZE - 8,
));
description = "Copy-on-write datastructures, storable on disk (or elsewhere) with a stable format."
authors = ["Pierre-Étienne Meunier", "Florent Becker"]
license = "MIT/Apache-2.0"
documentation = "https://docs.rs/sanakirja"
repository = "https://nest.pijul.com/pijul/sanakirja"
include = [
"Cargo.toml",
"src/lib.rs",
"src",
"src/btree",
"src/btree/page_cursor.rs",
"src/btree/page_unsized",
"src/btree/page_unsized/alloc.rs",
"src/btree/page_unsized/rebalance.rs",
"src/btree/page_unsized/header.rs",
"src/btree/page_unsized/put.rs",
"src/btree/page_unsized/cursor.rs",
"src/btree/put.rs",
"src/btree/page",
"src/btree/page/alloc.rs",
"src/btree/page/rebalance.rs",
"src/btree/page/put.rs",
"src/btree/del.rs",
"src/btree/mod.rs",
"src/btree/page_unsized.rs",
"src/btree/cursor.rs",
"src/btree/page.rs"
]
#[test]
pub fn put_growth() {
env_logger::try_init().unwrap_or(());
let path = tempfile::tempdir().unwrap();
let path = path.path().join("db");
let l0 = 1 << 13; // 2 pages
let env = Env::new(&path, l0, 1).unwrap();
let mut txn = Env::mut_txn_begin(&env).unwrap();
let mut db = create_db::<MutTxn<&Env, ()>, u64, u64>(&mut txn).unwrap();
let n = 100_000u64;
for i in 0..n {
put(&mut txn, &mut db, &i, &i).unwrap();
}
println!("{:?}", env.mmaps);
let len = std::fs::metadata(&path).unwrap().len();
assert_eq!(len, (l0 << 9) - l0);
}
#[cfg(feature = "mmap")]
#[test]
#[should_panic]
fn nroots_test() {
let path = tempfile::tempdir().unwrap();
let path = path.path().join("db");
let l0 = 1 << 15; // 8 pages
Env::new(&path, l0, 19).unwrap();
}
#[cfg(feature = "mmap")]
#[test]
fn mmap_growth_test() {
let path = tempfile::tempdir().unwrap();
let path = path.path().join("db");
let l0 = 1 << 15; // 8 pages
{
let env = Env::new(&path, l0, 2).unwrap();
let map1 = env.open_mmap(0, l0).unwrap();
println!("{:?}", map1);
let map2 = env.open_mmap(1, l0).unwrap();
println!("{:?}", map2);
map1.flush().unwrap();
map2.flush().unwrap();
}
let len = std::fs::metadata(&path).unwrap().len();
assert_eq!(len, (l0 << 2) - l0);
}
#[cfg(not(feature = "crc32"))]
fn set_crc(_ptr: *mut u8) {}
#[cfg(feature = "crc32")]
fn set_crc(ptr: *mut u8) {
unsafe {
let root_page = std::slice::from_raw_parts(ptr.add(8), PAGE_SIZE - 8);
let mut h = HASHER.clone();
h.update(root_page);
let globptr = ptr as *mut GlobalHeader;
(&mut *globptr).crc = h.finalize().to_le();
}
}
// let length = (1 as u64).shl(log_length);
let mut db_path = path.as_ref().join("db0");
let db_exists = std::fs::metadata(&db_path).is_ok();
let length = if let Ok(meta) = std::fs::metadata(&db_path) {
let db_exists = std::fs::metadata(&path).is_ok();
let length = if let Ok(meta) = std::fs::metadata(&path) {
let mut env = Self::new_nolock_mmap(Some(file), length, mmap, !db_exists, n_roots)?;
db_path.pop();
env.path = Some(db_path);
Ok(env)
Self::new_nolock_mmap(Some(file), length, mmap, !db_exists, n_roots)
GlobalHeader::from_le(&*(map as *const GlobalHeader))
} else {
GlobalHeader::from_le(&*(map as *const GlobalHeader))
};
}
let glob = GlobalHeader::from_le(&*(map as *const GlobalHeader));
if let Some(ref path) = self.path {
let mut db_path = path.join(&format!("db{}", i));
let file = OpenOptions::new()
.read(true)
.write(true)
.truncate(false)
.create(true)
.open(&db_path)?;
file.set_len(length)?;
db_path.pop();
let mut mmap = unsafe { memmap::MmapMut::map_mut(&file)? };
let offset = (length0 << i) - length0;
if let Some(ref file) = self.file {
file.set_len(offset + length)?;
let mut mmap = unsafe {
memmap::MmapOptions::new()
.offset(offset)
.len(length as usize)
.map_mut(&file)?
};
}
#[cfg(not(feature = "crc32"))]
fn check_crc(&self, _root: usize) -> Result<(), crate::CRCError> {
Ok(())
}
#[cfg(feature = "crc32")]
fn check_crc(&self, root: usize) -> Result<(), crate::CRCError> {
unsafe {
let maps = self.mmaps.lock();
let page_ptr = maps[0].ptr.add(root * PAGE_SIZE);
let crc = (&*(page_ptr as *const GlobalHeader)).crc;
let root_page = std::slice::from_raw_parts(page_ptr.add(8), PAGE_SIZE - 8);
let mut h = HASHER.clone();
h.update(root_page);
if h.finalize() != crc {
return Err(crate::CRCError {});
}
}
Ok(())
tempfile = "3.2"