open and create databases in transaction

without.crypto
Dan Burkert 10 years ago
parent 0d01789de9
commit ab7f551298
  1. 54
      src/database.rs
  2. 4
      src/environment.rs
  3. 42
      src/transaction.rs

@ -1,10 +1,9 @@
use libc::c_uint;
use std::ptr; use std::ptr;
use ffi; use ffi;
use error::{LmdbResult, lmdb_result}; use error::{LmdbResult, lmdb_result};
use flags::DatabaseFlags;
use transaction::{RwTransaction, Transaction};
/// A handle to an individual database in an environment. /// A handle to an individual database in an environment.
/// ///
@ -16,57 +15,26 @@ pub struct Database {
impl Database { impl Database {
/// Opens a database in the provided transaction. /// Opens a new database handle in the given transaction.
/// ///
/// If `name` is `None`, then the default database will be opened, otherwise a named database /// Prefer using `Environment::open_db`, `Environment::create_db`, `TransactionExt::open_db`,
/// will be opened. The database handle will be private to the transaction until the transaction /// or `RwTransaction::create_db`.
/// is successfully committed. If the transaction is aborted the returned database handle #[doc(hidden)]
/// should no longer be used. pub unsafe fn new(txn: *mut ffi::MDB_txn,
/// name: Option<&str>,
/// ## Unsafety flags: c_uint)
/// -> LmdbResult<Database> {
/// * This function (as well as `Environment::open_db`, `Environment::create_db`, and
/// `Database::create`) **must not** be called from multiple concurrent transactions in the same
/// environment. A transaction which uses this function must finish (either commit or abort)
/// before any other transaction may use this function.
pub unsafe fn open(txn: &Transaction,
name: Option<&str>)
-> LmdbResult<Database> {
let c_name = name.map(|n| n.to_c_str());
let name_ptr = if let Some(ref c_name) = c_name { c_name.as_ptr() } else { ptr::null() };
let mut dbi: ffi::MDB_dbi = 0;
try!(lmdb_result(ffi::mdb_dbi_open(txn.txn(), name_ptr, 0, &mut dbi)));
Ok(Database { dbi: dbi })
}
/// Opens a handle in the provided transaction, creating the database if necessary.
///
/// If `name` is `None`, then the default database will be opened, otherwise a named database
/// will be opened. The database handle will be private to the transaction until the transaction
/// is successfully committed. If the transaction is aborted the returned database handle
/// should no longer be used.
///
/// ## Unsafety
///
/// * This function (as well as `Environment::open_db`, `Environment::create_db`, and
/// `Database::open`) **must not** be called from multiple concurrent transactions in the same
/// environment. A transaction which uses this function must finish (either commit or abort)
/// before any other transaction may use this function.
pub unsafe fn create(txn: &RwTransaction,
name: Option<&str>,
flags: DatabaseFlags)
-> LmdbResult<Database> {
let c_name = name.map(|n| n.to_c_str()); let c_name = name.map(|n| n.to_c_str());
let name_ptr = if let Some(ref c_name) = c_name { c_name.as_ptr() } else { ptr::null() }; let name_ptr = if let Some(ref c_name) = c_name { c_name.as_ptr() } else { ptr::null() };
let mut dbi: ffi::MDB_dbi = 0; let mut dbi: ffi::MDB_dbi = 0;
try!(lmdb_result(ffi::mdb_dbi_open(txn.txn(), name_ptr, flags.bits() | ffi::MDB_CREATE, &mut dbi))); try!(lmdb_result(ffi::mdb_dbi_open(txn, name_ptr, flags, &mut dbi)));
Ok(Database { dbi: dbi }) Ok(Database { dbi: dbi })
} }
/// Returns the underlying LMDB database handle. /// Returns the underlying LMDB database handle.
/// ///
/// The caller **must** ensure that the handle is not used after the lifetime of the /// The caller **must** ensure that the handle is not used after the lifetime of the
/// environment, or after the database handle has been closed. /// environment, or after the database has been closed.
pub fn dbi(&self) -> ffi::MDB_dbi { pub fn dbi(&self) -> ffi::MDB_dbi {
self.dbi self.dbi
} }

@ -53,7 +53,7 @@ impl Environment {
pub fn open_db<'env>(&'env self, name: Option<&str>) -> LmdbResult<Database> { pub fn open_db<'env>(&'env self, name: Option<&str>) -> LmdbResult<Database> {
let mutex = self.dbi_open_mutex.lock(); let mutex = self.dbi_open_mutex.lock();
let txn = try!(self.begin_ro_txn()); let txn = try!(self.begin_ro_txn());
let db = unsafe { try!(Database::open(&txn, name)) }; let db = unsafe { try!(txn.open_db(name)) };
try!(txn.commit()); try!(txn.commit());
drop(mutex); drop(mutex);
Ok(db) Ok(db)
@ -79,7 +79,7 @@ impl Environment {
-> LmdbResult<Database> { -> LmdbResult<Database> {
let mutex = self.dbi_open_mutex.lock(); let mutex = self.dbi_open_mutex.lock();
let txn = try!(self.begin_rw_txn()); let txn = try!(self.begin_rw_txn());
let db = unsafe { try!(Database::create(&txn, name, flags)) }; let db = unsafe { try!(txn.create_db(name, flags)) };
try!(txn.commit()); try!(txn.commit());
drop(mutex); drop(mutex);
Ok(db) Ok(db)

@ -44,6 +44,25 @@ pub trait TransactionExt<'env> : Transaction<'env> {
// Abort should be performed in transaction destructors. // Abort should be performed in transaction destructors.
} }
/// Opens a database in the transaction.
///
/// If `name` is `None`, then the default database will be opened, otherwise a named database
/// will be opened. The database handle will be private to the transaction until the transaction
/// is successfully committed. If the transaction is aborted the returned database handle
/// should no longer be used.
///
/// Prefer using `Environment::open_db`.
///
/// ## Unsafety
///
/// This function (as well as `Environment::open_db`, `Environment::create_db`, and
/// `Database::create`) **must not** be called from multiple concurrent transactions in the same
/// environment. A transaction which uses this function must finish (either commit or abort)
/// before any other transaction may use this function.
unsafe fn open_db(&self, name: Option<&str>) -> LmdbResult<Database> {
Database::new(self.txn(), name, 0)
}
/// Gets an item from a database. /// Gets an item from a database.
/// ///
/// This function retrieves the data associated with the given key in the database. If the /// This function retrieves the data associated with the given key in the database. If the
@ -225,6 +244,29 @@ impl <'env> RwTransaction<'env> {
} }
} }
/// Opens a database in the provided transaction, creating it if necessary.
///
/// If `name` is `None`, then the default database will be opened, otherwise a named database
/// will be opened. The database handle will be private to the transaction until the transaction
/// is successfully committed. If the transaction is aborted the returned database handle
/// should no longer be used.
///
/// Prefer using `Environment::create_db`.
///
/// ## Unsafety
///
/// * This function (as well as `Environment::open_db`, `Environment::create_db`, and
/// `Database::open`) **must not** be called from multiple concurrent transactions in the same
/// environment. A transaction which uses this function must finish (either commit or abort)
/// before any other transaction may use this function.
pub unsafe fn create_db(&self,
name: Option<&str>,
flags: DatabaseFlags)
-> LmdbResult<Database> {
Database::new(self.txn(), name, flags.bits() | ffi::MDB_CREATE)
}
/// Opens a new read-write cursor on the given database and transaction. /// Opens a new read-write cursor on the given database and transaction.
pub fn open_rw_cursor<'txn>(&'txn mut self, db: Database) -> LmdbResult<RwCursor<'txn>> { pub fn open_rw_cursor<'txn>(&'txn mut self, db: Database) -> LmdbResult<RwCursor<'txn>> {
RwCursor::new(self, db) RwCursor::new(self, db)

Loading…
Cancel
Save