New file locks, with multiple sets of free pages
[?]
Feb 1, 2021, 6:43 PM
YXKP4AIWDBIWBBUDWF66YIPG5ECMHNKEV3PX6KYXOVXY3EWG3WGQCDependencies
- [2]
WS4ZQM4RDebugging, tests, etc. - [3]
EAAYH6BQDebugging put - [4]
FMN7X4J2Micro-improvements, now noticeably faster than std::collections::BTreeMap - [5]
OP6SVMODResetting history - [6]
PXF3R6SVImproving test coverage for btree::cursor - [7]
ONES3V46reference counting works for put
Change contents
- replacement in sanakirja/src/environment/muttxn.rs at line 6
impl<E:Borrow<Env<Exclusive>>, T> std::fmt::Debug for MutTxn<E, T> {impl<E:Borrow<Env>, T> std::fmt::Debug for MutTxn<E, T> { - replacement in sanakirja/src/environment/muttxn.rs at line 13
pub struct MutTxn<E: Borrow<Env<Exclusive>>, T> {pub struct MutTxn<E: Borrow<Env>, T> { - replacement in sanakirja/src/environment/muttxn.rs at line 33
impl<E: Borrow<Env<Exclusive>>, T> Drop for MutTxn<E, T> {impl<E: Borrow<Env>, T> Drop for MutTxn<E, T> { - replacement in sanakirja/src/environment/muttxn.rs at line 38
env.roots[*root].unlock_exclusive()env.roots[*root].rw.unlock_exclusive();if let Some(ref f) = env.roots[*root].lock_file {f.unlock().unwrap_or(())} - replacement in sanakirja/src/environment/muttxn.rs at line 52
impl<'a, E: Borrow<Env<Exclusive>>, T> Commit for MutTxn<E, &'a mut MutTxn<E, T>> {impl<'a, E: Borrow<Env>, T> Commit for MutTxn<E, &'a mut MutTxn<E, T>> { - replacement in sanakirja/src/environment/muttxn.rs at line 72
impl Env<Exclusive> {impl Env { - replacement in sanakirja/src/environment/muttxn.rs at line 82
env_.roots[(*v + 1) % n].lock_exclusive();env_.roots[*v].rw.lock_exclusive();if let Some(ref f) = env_.roots[*v].lock_file {f.lock_exclusive()?} - edit in sanakirja/src/environment/muttxn.rs at line 87
// Root of the last MutTxn.let v0 = *v + n - 1; - replacement in sanakirja/src/environment/muttxn.rs at line 90
let page_ptr = maps.offset((*v * PAGE_SIZE) as isize);let next_page_ptr = maps.offset((((*v + 1) % n) * PAGE_SIZE) as isize);let page_ptr = maps.offset((v0 * PAGE_SIZE) as isize);let next_page_ptr = maps.offset((*v * PAGE_SIZE) as isize); - replacement in sanakirja/src/environment/muttxn.rs at line 131
impl<E: Borrow<Env<Exclusive>>> Commit for MutTxn<E, ()> {impl<E: Borrow<Env>> Commit for MutTxn<E, ()> { - edit in sanakirja/src/environment/muttxn.rs at line 164
(&mut *globptr).root = ((&mut *globptr).root + 1) % (&mut *globptr).n_roots; - edit in sanakirja/src/environment/muttxn.rs at line 165
(&mut *globptr).root = *root as u8; - edit in sanakirja/src/environment/muttxn.rs at line 170
env.roots[*root].rw.unlock_exclusive();if let Some(ref f) = env.roots[*root].lock_file {f.unlock().unwrap_or(())} - replacement in sanakirja/src/environment/muttxn.rs at line 180
impl<E: Borrow<Env<Exclusive>>, T> MutTxn<E, T> {impl<E: Borrow<Env>, T> MutTxn<E, T> { - replacement in sanakirja/src/environment/muttxn.rs at line 214
impl<E: Borrow<Env<Exclusive>>, T> sanakirja_core::AllocPage for MutTxn<E, T> {impl<E: Borrow<Env>, T> sanakirja_core::AllocPage for MutTxn<E, T> { - replacement in sanakirja/src/environment/muttxn.rs at line 336
impl<E: Borrow<Env<Exclusive>>, A> sanakirja_core::LoadPage for MutTxn<E, A> {impl<E: Borrow<Env>, A> sanakirja_core::LoadPage for MutTxn<E, A> { - replacement in sanakirja/src/environment/mod.rs at line 4
use std::borrow::Borrow;use std::path::Path;#[cfg(feature = "mmap")]use fs2::FileExt; - edit in sanakirja/src/environment/mod.rs at line 8
use std::borrow::Borrow;#[cfg(not(feature = "mmap"))]use std::path::Path;#[cfg(feature = "mmap")]use std::path::{Path, PathBuf};#[cfg(feature = "mmap")]use std::fs::OpenOptions;use std::sync::atomic::{AtomicUsize, Ordering}; - edit in sanakirja/src/environment/mod.rs at line 46
}}/// Represents an exclusive lock taken on the environment.pub struct Exclusive(std::fs::File);#[cfg(feature = "mmap")]impl Drop for Exclusive {fn drop(&mut self) {self.0.unlock().unwrap_or(());}}/// Represents a shared lock taken on the environment.pub struct Shared(std::fs::File);#[cfg(feature = "mmap")]impl Drop for Shared {fn drop(&mut self) {self.0.unlock().unwrap_or(()); - replacement in sanakirja/src/environment/mod.rs at line 60
pub struct Env<T> {pub struct Env { - edit in sanakirja/src/environment/mod.rs at line 63
/// It is undefined behavior to have a file mmapped for than once.#[cfg(feature = "mmap")]lock_file: Option<T>,#[cfg(not(feature = "mmap"))]lock_file: std::marker::PhantomData<T>, - replacement in sanakirja/src/environment/mod.rs at line 67
roots: Vec<parking_lot::RawRwLock>,roots: Vec<RootLock>,// Root number of the next MutTxn. - replacement in sanakirja/src/environment/mod.rs at line 72
unsafe impl<T> Send for Env<T> {}unsafe impl<T> Sync for Env<T> {}struct RootLock {/// It is undefined behavior to have a file mmapped for than once.#[cfg(feature = "mmap")]lock_file: Option<std::fs::File>,rw: parking_lot::RawRwLock,n_txn: AtomicUsize,}unsafe impl Send for Env {}unsafe impl Sync for Env {} - replacement in sanakirja/src/environment/mod.rs at line 85
impl<T> Drop for Env<T> {impl Drop for Env { - replacement in sanakirja/src/environment/mod.rs at line 87
for map in self.mmaps.lock().unwrap().drain(..) {for map in self.mmaps.lock().drain(..) { - replacement in sanakirja/src/environment/mod.rs at line 95
impl<T> Drop for Env<T> {impl Drop for Env { - replacement in sanakirja/src/environment/mod.rs at line 105
pub struct Txn<L, E: Borrow<Env<L>>> {pub struct Txn<E: Borrow<Env>> { - edit in sanakirja/src/environment/mod.rs at line 107
lock: std::marker::PhantomData<L>, - replacement in sanakirja/src/environment/mod.rs at line 110
impl<T> Env<T> {impl Env { - replacement in sanakirja/src/environment/mod.rs at line 129
pub unsafe fn new_nolock<P: AsRef<Path>>(path: P, length: u64) -> Result<Self, Error> {pub unsafe fn new_nolock<P: AsRef<Path>>(path: P, length: u64, n_roots: usize) -> Result<Self, Error> { - replacement in sanakirja/src/environment/mod.rs at line 138
let length = length.next_power_of_two();let length = (length + 4095) & !4096; - replacement in sanakirja/src/environment/mod.rs at line 147
let mut env = Self::new_nolock_mmap(Some(file), length, mmap, !db_exists)?;let mut env = Self::new_nolock_mmap(Some(file), length, mmap, !db_exists, n_roots)?; - edit in sanakirja/src/environment/mod.rs at line 159
n_roots: usize, - edit in sanakirja/src/environment/mod.rs at line 162
let n_roots = 2; - replacement in sanakirja/src/environment/mod.rs at line 164
*(map.offset(i * PAGE_SIZE) as *mut GlobalHeader) = GlobalHeader {*(map.add(i * PAGE_SIZE) as *mut GlobalHeader) = GlobalHeader { - replacement in sanakirja/src/environment/mod.rs at line 167
n_roots,n_roots: n_roots as u8, - replacement in sanakirja/src/environment/mod.rs at line 169
length: n_roots * PAGE_SIZE,length, - replacement in sanakirja/src/environment/mod.rs at line 174
GlobalHeader::from_le(*(map as *const GlobalHeader))GlobalHeader::from_le(&*(map as *const GlobalHeader)) - replacement in sanakirja/src/environment/mod.rs at line 176
GlobalHeader::from_le(*(map as *const GlobalHeader))GlobalHeader::from_le(&*(map as *const GlobalHeader)) - replacement in sanakirja/src/environment/mod.rs at line 178
let mut versions = Vec::with_capacity(glob.n_versions as usize);for _ in 0..glob.n_versions {versions.push(Mutex::new(()))let mut roots = Vec::with_capacity(glob.n_roots as usize);for _ in 0..glob.n_roots {roots.push(RootLock {rw: <parking_lot::RawRwLock as parking_lot::lock_api::RawRwLock>::INIT,n_txn: AtomicUsize::new(0),lock_file: None,}) - edit in sanakirja/src/environment/mod.rs at line 194
lock_file: None, - replacement in sanakirja/src/environment/mod.rs at line 195
mutable: parking_lot::RawMutex::INIT,versions,roots,root: Mutex::new(glob.root as usize), - replacement in sanakirja/src/environment/mod.rs at line 202
unsafe fn new_nolock_mmap(length: u64, initialise: bool) -> Result<Env<Exclusive>, Error> {unsafe fn new_nolock_mmap(length: u64, initialise: bool) -> Result<Env, Error> { - replacement in sanakirja/src/environment/mod.rs at line 222
roots.push(<parking_lot::RawRwLock as parking_lot::lock_api::RawRwLock>::INIT)roots.push(RootLock {rw: <parking_lot::RawRwLock as parking_lot::lock_api::RawRwLock>::INIT,n_txn: AtomicUsize::new(0),}) - edit in sanakirja/src/environment/mod.rs at line 233
lock_file: std::marker::PhantomData, - replacement in sanakirja/src/environment/mod.rs at line 241
impl Env<Shared> {/// Initialize an environment. `length` must be a strictly/// positive multiple of 4096. The same file can only be open in/// one process or thread at the same time, and this is enforced/// by a locked file.#[cfg(feature = "mmap")]pub fn new_shared<P: AsRef<Path>>(path: P, length: u64) -> Result<Env<Shared>, Error> {let lock_file = OpenOptions::new().read(true).write(true).truncate(false).create(true).open(path.as_ref().join("db").with_extension("lock"))?;lock_file.lock_shared()?;let mut env = unsafe { Self::new_nolock(path, length)? };env.lock_file = Some(Shared(lock_file));Ok(env)}impl Env { - replacement in sanakirja/src/environment/mod.rs at line 244
/// positive multiple of 4096. Returns an error if the database is/// locked by another process or thread./// positive multiple of 4096.////// The `n_roots` parameter is the maximum number of mutable/// transactions that can commit during a single immutable/// transaction, and must be at most 255. If it is 1, mutable/// transactions exclude all immutable transactions. - replacement in sanakirja/src/environment/mod.rs at line 251
pub fn try_new_shared<P: AsRef<Path>>(path: P, length: u64) -> Result<Env<Shared>, Error> {let lock_file = OpenOptions::new().read(true).write(true).truncate(false).create(true).open(path.as_ref().join("db").with_extension("lock"))?;lock_file.try_lock_shared()?;let mut env = unsafe { Self::new_nolock(path, length)? };env.lock_file = Some(Shared(lock_file));Ok(env)}}impl Env<Exclusive> {/// Initialize an environment. `length` must be a strictly/// positive multiple of 4096. The same file can only be open in/// one process or thread at the same time, and this is enforced/// by a locked file.#[cfg(feature = "mmap")]pub fn new<P: AsRef<Path>>(path: P, length: u64) -> Result<Env<Exclusive>, Error> {let lock_file = OpenOptions::new().read(true).write(true).truncate(false).create(true).open(path.as_ref().join("db").with_extension("lock"))?;lock_file.lock_exclusive()?;let mut env = unsafe { Self::new_nolock(path, length)? };env.lock_file = Some(Exclusive(lock_file));Ok(env)}/// Initialize an environment. `length` must be a strictly/// positive multiple of 4096. Returns an error if the database is/// locked by another process or thread.#[cfg(feature = "mmap")]pub fn try_new<P: AsRef<Path>>(path: P, length: u64) -> Result<Env<Exclusive>, Error> {let lock_file = OpenOptions::new().read(true).write(true).truncate(false).create(true).open(path.as_ref().join("db").with_extension("lock"))?;lock_file.try_lock_exclusive()?;let mut env = unsafe { Self::new_nolock(path, length)? };env.lock_file = Some(Exclusive(lock_file));pub fn new<P: AsRef<Path>>(path: P, length: u64, n_roots: usize) -> Result<Env, Error> {assert!(n_roots < 256);let path = path.as_ref();let mut env = unsafe { Self::new_nolock(path, length, n_roots)? };for (n, l) in env.roots.iter_mut().enumerate() {l.lock_file = Some(OpenOptions::new().read(true).write(true).truncate(false).create(true).open(path.join("db").with_extension(&format!("lock{}", n)))?);} - replacement in sanakirja/src/environment/mod.rs at line 271
pub fn new_anon(length: u64) -> Result<Env<Exclusive>, Error> {let length = std::cmp::max(length, 4096).next_power_of_two();pub fn new_anon(length: u64, n_roots: usize) -> Result<Env, Error> {let length = (std::cmp::max(length, 4096) + 4095) & !4096; - replacement in sanakirja/src/environment/mod.rs at line 274
unsafe { Self::new_nolock_mmap(None, length, mmap, true) }unsafe { Self::new_nolock_mmap(None, length, mmap, true, n_roots) } - replacement in sanakirja/src/environment/mod.rs at line 280
pub fn new_anon(length: u64) -> Result<Env<Exclusive>, Error> {pub fn new_anon(length: u64) -> Result<Env, Error> { - edit in sanakirja/src/environment/mod.rs at line 284
} - edit in sanakirja/src/environment/mod.rs at line 285
impl<L> Env<L> { - replacement in sanakirja/src/environment/mod.rs at line 354
for m in self.mmaps.lock().unwrap().drain(..) {for m in self.mmaps.lock().drain(..) { - replacement in sanakirja/src/environment/mod.rs at line 357
if let Some(lock_file) = self.lock_file.take() {drop(lock_file)for l in self.roots.drain(..) {if let Some(ref f) = l.lock_file {f.unlock().unwrap_or(())} - replacement in sanakirja/src/environment/mod.rs at line 377
impl<L> Env<L> {impl Env { - replacement in sanakirja/src/environment/mod.rs at line 379
pub fn txn_begin<E: Borrow<Self>>(env: E) -> Result<Txn<L, E>, Error> {pub fn txn_begin<E: Borrow<Self>>(env: E) -> Result<Txn<E>, Error> { - replacement in sanakirja/src/environment/mod.rs at line 384
env_.roots[root].lock_shared();let old_n_txn = env_.roots[root].n_txn.fetch_add(1, Ordering::SeqCst);if old_n_txn == 0 {env_.roots[root].rw.lock_shared();if let Some(ref f) = env_.roots[root].lock_file {f.lock_shared()?;}} - replacement in sanakirja/src/environment/mod.rs at line 394
Ok(Txn {env,lock: std::marker::PhantomData,root,})Ok(Txn { env, root }) - replacement in sanakirja/src/environment/mod.rs at line 398
impl<L, E: Borrow<Env<L>>> Drop for Txn<L, E> {impl<E: Borrow<Env>> Drop for Txn<E> { - replacement in sanakirja/src/environment/mod.rs at line 401
unsafe { env.roots[self.root].unlock_shared() }let old_n_txn = env.roots[self.root].n_txn.fetch_sub(1, Ordering::SeqCst);if old_n_txn == 1 {unsafe { env.roots[self.root].rw.unlock_shared() }if let Some(ref f) = env.roots[self.root].lock_file {f.unlock().unwrap_or(())}} - replacement in sanakirja/src/environment/mod.rs at line 411
impl<L, E: Borrow<Env<L>>> sanakirja_core::LoadPage for Txn<L, E> {impl<E: Borrow<Env>> sanakirja_core::LoadPage for Txn<E> { - edit in sanakirja/Cargo.toml at line 8
[features]default = [ "mmap" ]mmap = [ "memmap", "fs2" ] - edit in sanakirja/Cargo.toml at line 17
# lmdb-rs = "*"memmap = { version = "0.7", optional = true }fs2 = { version = "0.4", optional = true }sanakirja-core = { path = "../sanakirja-core", version = "*" }[dev-dependencies] - edit in sanakirja/Cargo.toml at line 24
lmdb-rs = "*"sanakirja-core = { path = "../sanakirja-core", version = "*" }