From ab7f5512984cd9299a00e4f887f4c12edc13eb39 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 21 Dec 2014 21:40:25 -0800 Subject: [PATCH] open and create databases in transaction --- src/database.rs | 54 ++++++++++------------------------------------ src/environment.rs | 4 ++-- src/transaction.rs | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/database.rs b/src/database.rs index c9f9208..73e9a33 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,10 +1,9 @@ +use libc::c_uint; use std::ptr; use ffi; use error::{LmdbResult, lmdb_result}; -use flags::DatabaseFlags; -use transaction::{RwTransaction, Transaction}; /// A handle to an individual database in an environment. /// @@ -16,57 +15,26 @@ pub struct 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 - /// 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::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 { - 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 { + /// Prefer using `Environment::open_db`, `Environment::create_db`, `TransactionExt::open_db`, + /// or `RwTransaction::create_db`. + #[doc(hidden)] + pub unsafe fn new(txn: *mut ffi::MDB_txn, + name: Option<&str>, + flags: c_uint) + -> LmdbResult { 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, flags.bits() | ffi::MDB_CREATE, &mut dbi))); + try!(lmdb_result(ffi::mdb_dbi_open(txn, name_ptr, flags, &mut dbi))); Ok(Database { dbi: dbi }) } /// Returns the underlying LMDB database handle. /// /// 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 { self.dbi } diff --git a/src/environment.rs b/src/environment.rs index 1fb96a9..bf0e967 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -53,7 +53,7 @@ impl Environment { pub fn open_db<'env>(&'env self, name: Option<&str>) -> LmdbResult { let mutex = self.dbi_open_mutex.lock(); 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()); drop(mutex); Ok(db) @@ -79,7 +79,7 @@ impl Environment { -> LmdbResult { let mutex = self.dbi_open_mutex.lock(); 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()); drop(mutex); Ok(db) diff --git a/src/transaction.rs b/src/transaction.rs index 902fd5f..b538b78 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -44,6 +44,25 @@ pub trait TransactionExt<'env> : Transaction<'env> { // 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::new(self.txn(), name, 0) + } + /// Gets an item from a database. /// /// 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::new(self.txn(), name, flags.bits() | ffi::MDB_CREATE) + } + + /// 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::new(self, db)