YXKP4AIWDBIWBBUDWF66YIPG5ECMHNKEV3PX6KYXOVXY3EWG3WGQC
}
}
/// 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(());
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 {}
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,
})
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 {
/// 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.
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)))?
);
}
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;
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(())
}
}