Skip to content

Commit

Permalink
Don't reopen LMDB databases (#201)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Mar 29, 2022
1 parent 11e99db commit 469de89
Showing 1 changed file with 42 additions and 48 deletions.
90 changes: 42 additions & 48 deletions src/lmdb_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,52 @@ impl<T> LmdbResultExt<T> for lmdb::Result<T> {
}
}

pub(crate) struct Database(Environment);
pub(crate) struct Database {
environment: Arc<Environment>,
height_to_hash: lmdb::Database<'static>,
outpoint_to_ordinal_ranges: lmdb::Database<'static>,
}

impl Database {
pub(crate) fn open(options: &Options) -> Result<Self> {
let path = "index.lmdb";

fs::create_dir_all(path)?;

let env = unsafe {
let environment = unsafe {
let mut builder = EnvBuilder::new()?;

builder.set_maxdbs(3)?;
builder.set_mapsize(options.index_size.0)?;

builder
.open(path, lmdb::open::Flags::empty(), 0o600)
.unwrap()
Arc::new(builder.open(path, lmdb::open::Flags::empty(), 0o600)?)
};

Ok(Self(env))
let height_to_hash = lmdb::Database::open(
environment.clone(),
Some(HEIGHT_TO_HASH),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?;

let outpoint_to_ordinal_ranges = lmdb::Database::open(
environment.clone(),
Some(OUTPOINT_TO_ORDINAL_RANGES),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?;

Ok(Self {
environment,
height_to_hash,
outpoint_to_ordinal_ranges,
})
}

pub(crate) fn begin_write(&self) -> Result<WriteTransaction> {
WriteTransaction::new(&self.0)
WriteTransaction::new(self)
}

pub(crate) fn print_info(&self) -> Result {
let stat = self.0.stat()?;
let stat = self.environment.stat()?;

let blocks_indexed = self.height()?;

Expand All @@ -62,16 +80,10 @@ impl Database {
}

pub(crate) fn height(&self) -> Result<u64> {
let height_to_hash = lmdb::Database::open(
&self.0,
Some(HEIGHT_TO_HASH),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?;

let tx = lmdb::ReadTransaction::new(&self.0)?;
let tx = lmdb::ReadTransaction::new(self.environment.clone())?;

let height = tx
.cursor(&height_to_hash)?
.cursor(&self.height_to_hash)?
.last::<[u8], [u8]>(&tx.access())
.into_option()?
.map(|(key, _value)| u64::from_be_bytes(key.try_into().unwrap()) + 1)
Expand All @@ -81,48 +93,30 @@ impl Database {
}

pub(crate) fn list(&self, outpoint: &[u8]) -> Result<Option<Vec<u8>>> {
let outpoint_to_ordinal_ranges = &lmdb::Database::open(
&self.0,
Some(OUTPOINT_TO_ORDINAL_RANGES),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?;

Ok(
lmdb::ReadTransaction::new(&self.0)?
lmdb::ReadTransaction::new(self.environment.clone())?
.access()
.get::<[u8], [u8]>(outpoint_to_ordinal_ranges, outpoint)
.get::<[u8], [u8]>(&self.outpoint_to_ordinal_ranges, outpoint)
.into_option()?
.map(|ranges| ranges.to_vec()),
)
}
}

pub(crate) struct WriteTransaction<'a> {
height_to_hash: lmdb::Database<'a>,
height_to_hash: &'a lmdb::Database<'static>,
lmdb_write_transaction: lmdb::WriteTransaction<'a>,
outpoint_to_ordinal_ranges: lmdb::Database<'a>,
outpoint_to_ordinal_ranges: &'a lmdb::Database<'static>,
}

impl<'a> WriteTransaction<'a> {
pub(crate) fn new(environment: &'a Environment) -> Result<Self> {
let height_to_hash = lmdb::Database::open(
environment,
Some(HEIGHT_TO_HASH),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?;

let outpoint_to_ordinal_ranges = lmdb::Database::open(
environment,
Some(OUTPOINT_TO_ORDINAL_RANGES),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?;

let lmdb_write_transaction = lmdb::WriteTransaction::new(environment)?;
pub(crate) fn new(database: &'a Database) -> Result<Self> {
let lmdb_write_transaction = lmdb::WriteTransaction::new(database.environment.clone())?;

Ok(Self {
lmdb_write_transaction,
height_to_hash,
outpoint_to_ordinal_ranges,
height_to_hash: &database.height_to_hash,
outpoint_to_ordinal_ranges: &database.outpoint_to_ordinal_ranges,
})
}

Expand All @@ -134,7 +128,7 @@ impl<'a> WriteTransaction<'a> {
Ok(
self
.lmdb_write_transaction
.cursor(&self.height_to_hash)?
.cursor(self.height_to_hash)?
.last::<[u8], [u8]>(&self.lmdb_write_transaction.access())
.into_option()?
.map(|(key, _value)| u64::from_be_bytes(key.try_into().unwrap()) + 1)
Expand All @@ -147,15 +141,15 @@ impl<'a> WriteTransaction<'a> {
self
.lmdb_write_transaction
.access()
.get::<[u8], [u8]>(&self.height_to_hash, &height.to_be_bytes())
.get::<[u8], [u8]>(self.height_to_hash, &height.to_be_bytes())
.into_option()?
.map(|value| value.to_vec()),
)
}

pub(crate) fn set_blockhash_at_height(&mut self, height: u64, blockhash: BlockHash) -> Result {
self.lmdb_write_transaction.access().put(
&self.height_to_hash,
self.height_to_hash,
&height.to_be_bytes(),
blockhash.as_ref(),
lmdb::put::Flags::empty(),
Expand All @@ -165,7 +159,7 @@ impl<'a> WriteTransaction<'a> {

pub(crate) fn insert_outpoint(&mut self, outpoint: &[u8], ordinal_ranges: &[u8]) -> Result {
self.lmdb_write_transaction.access().put(
&self.outpoint_to_ordinal_ranges,
self.outpoint_to_ordinal_ranges,
outpoint,
ordinal_ranges,
lmdb::put::Flags::empty(),
Expand All @@ -177,7 +171,7 @@ impl<'a> WriteTransaction<'a> {
self
.lmdb_write_transaction
.access()
.del_key(&self.outpoint_to_ordinal_ranges, outpoint)?;
.del_key(self.outpoint_to_ordinal_ranges, outpoint)?;
Ok(())
}

Expand All @@ -186,7 +180,7 @@ impl<'a> WriteTransaction<'a> {
self
.lmdb_write_transaction
.access()
.get::<[u8], [u8]>(&self.outpoint_to_ordinal_ranges, outpoint)
.get::<[u8], [u8]>(self.outpoint_to_ordinal_ranges, outpoint)
.into_option()?
.map(|value| value.to_vec()),
)
Expand Down

0 comments on commit 469de89

Please sign in to comment.