Fix readonly check in libmdbx-rs (#12096)

This commit is contained in:
lazymio
2024-10-27 00:17:21 +08:00
committed by GitHub
parent f616de6d94
commit b257408060
4 changed files with 41 additions and 10 deletions

View File

@ -126,7 +126,7 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> Environmen
.static_file_provider()
.check_consistency(&factory.provider()?, has_receipt_pruning)?
{
if factory.db_ref().is_read_only() {
if factory.db_ref().is_read_only()? {
warn!(target: "reth::cli", ?unwind_target, "Inconsistent storage. Restart node to heal.");
return Ok(factory)
}

View File

@ -4,7 +4,7 @@ use crate::{
flags::EnvironmentFlags,
transaction::{RO, RW},
txn_manager::{TxnManager, TxnManagerMessage, TxnPtr},
Transaction, TransactionKind,
Mode, SyncMode, Transaction, TransactionKind,
};
use byteorder::{ByteOrder, NativeEndian};
use mem::size_of;
@ -72,14 +72,14 @@ impl Environment {
/// Returns true if the environment was opened in [`crate::Mode::ReadWrite`] mode.
#[inline]
pub fn is_read_write(&self) -> bool {
self.inner.env_kind.is_write_map()
pub fn is_read_write(&self) -> Result<bool> {
Ok(!self.is_read_only()?)
}
/// Returns true if the environment was opened in [`crate::Mode::ReadOnly`] mode.
#[inline]
pub fn is_read_only(&self) -> bool {
!self.inner.env_kind.is_write_map()
pub fn is_read_only(&self) -> Result<bool> {
Ok(matches!(self.info()?.mode(), Mode::ReadOnly))
}
/// Returns the transaction manager.
@ -425,6 +425,23 @@ impl Info {
fsync: self.0.mi_pgop_stat.fsync,
}
}
/// Return the mode of the database
#[inline]
pub const fn mode(&self) -> Mode {
let mode = self.0.mi_mode;
if (mode & ffi::MDBX_RDONLY) != 0 {
Mode::ReadOnly
} else if (mode & ffi::MDBX_UTTERLY_NOSYNC) != 0 {
Mode::ReadWrite { sync_mode: SyncMode::UtterlyNoSync }
} else if (mode & ffi::MDBX_NOMETASYNC) != 0 {
Mode::ReadWrite { sync_mode: SyncMode::NoMetaSync }
} else if (mode & ffi::MDBX_SAFE_NOSYNC) != 0 {
Mode::ReadWrite { sync_mode: SyncMode::SafeNoSync }
} else {
Mode::ReadWrite { sync_mode: SyncMode::Durable }
}
}
}
impl fmt::Debug for Environment {
@ -781,15 +798,14 @@ impl EnvironmentBuilder {
}
/// Sets the interprocess/shared threshold to force flush the data buffers to disk, if
/// [`SyncMode::SafeNoSync`](crate::flags::SyncMode::SafeNoSync) is used.
/// [`SyncMode::SafeNoSync`] is used.
pub fn set_sync_bytes(&mut self, v: usize) -> &mut Self {
self.sync_bytes = Some(v as u64);
self
}
/// Sets the interprocess/shared relative period since the last unsteady commit to force flush
/// the data buffers to disk, if [`SyncMode::SafeNoSync`](crate::flags::SyncMode::SafeNoSync) is
/// used.
/// the data buffers to disk, if [`SyncMode::SafeNoSync`] is used.
pub fn set_sync_period(&mut self, v: Duration) -> &mut Self {
// For this option, mdbx uses units of 1/65536 of a second.
let as_mdbx_units = (v.as_secs_f64() * 65536f64) as u64;

View File

@ -6,7 +6,7 @@ use crate::{
txn_manager::{TxnManagerMessage, TxnPtr},
Cursor, Error, Stat, TableObject,
};
use ffi::{mdbx_txn_renew, MDBX_txn_flags_t, MDBX_TXN_RDONLY, MDBX_TXN_READWRITE};
use ffi::{MDBX_txn_flags_t, MDBX_TXN_RDONLY, MDBX_TXN_READWRITE};
use indexmap::IndexSet;
use parking_lot::{Mutex, MutexGuard};
use std::{
@ -18,6 +18,9 @@ use std::{
time::Duration,
};
#[cfg(feature = "read-tx-timeouts")]
use ffi::mdbx_txn_renew;
mod private {
use super::*;

View File

@ -128,6 +128,18 @@ fn test_info() {
// assert_eq!(info.last_pgno(), 1);
// assert_eq!(info.last_txnid(), 0);
assert_eq!(info.num_readers(), 0);
assert!(matches!(info.mode(), Mode::ReadWrite { sync_mode: SyncMode::Durable }));
assert!(env.is_read_write().unwrap());
drop(env);
let env = Environment::builder()
.set_geometry(Geometry { size: Some(map_size..), ..Default::default() })
.set_flags(EnvironmentFlags { mode: Mode::ReadOnly, ..Default::default() })
.open(dir.path())
.unwrap();
let info = env.info().unwrap();
assert!(matches!(info.mode(), Mode::ReadOnly));
assert!(env.is_read_only().unwrap());
}
#[test]